From af1bc3fcc42cbcd085e458f00801b65ef1c81c5f Mon Sep 17 00:00:00 2001 From: Mauro Piazza Date: Fri, 21 Jun 2024 19:34:32 +0200 Subject: [PATCH] chore(XERC20): add script to compare our version w/ upstream --- .prettierrc | 1 + solidity/src/test/XERC20.sol | 102 ++++++---------------------- solidity/src/test/XERC20Lockbox.sol | 16 +---- solidity/src/test/diff-standard.sh | 10 +++ 4 files changed, 36 insertions(+), 93 deletions(-) create mode 100755 solidity/src/test/diff-standard.sh diff --git a/.prettierrc b/.prettierrc index a8bf3ef7..0b774d1e 100644 --- a/.prettierrc +++ b/.prettierrc @@ -7,6 +7,7 @@ "overrides": [ { "files": "*.sol", + "excludeFiles": [ "XER20.sol", "XERC20Lockbox.sol" ], "options": { "printWidth": 80, "tabWidth": 4, diff --git a/solidity/src/test/XERC20.sol b/solidity/src/test/XERC20.sol index 6ce66a53..aee98243 100644 --- a/solidity/src/test/XERC20.sol +++ b/solidity/src/test/XERC20.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.4 <0.9.0; -import {IXERC20} from "../interfaces/IXERC20.sol"; -import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol"; -import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import {IXERC20} from '../interfaces/IXERC20.sol'; +import {ERC20} from '@openzeppelin/contracts/token/ERC20/ERC20.sol'; +import {ERC20Permit} from '@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol'; +import {Ownable} from '@openzeppelin/contracts/access/Ownable.sol'; import {IFeesManager} from "../interfaces/IFeesManager.sol"; contract XERC20 is ERC20, Ownable, IXERC20, ERC20Permit { @@ -15,9 +15,8 @@ contract XERC20 is ERC20, Ownable, IXERC20, ERC20Permit { /** * @notice The address of the factory which deployed this contract - * @dev Unused for this implementation */ - // address public immutable FACTORY; + address public immutable FACTORY; /** * @notice The address of the lockbox contract @@ -29,15 +28,8 @@ contract XERC20 is ERC20, Ownable, IXERC20, ERC20Permit { */ mapping(address => Bridge) public bridges; - /** - * @notice Contract where the fees are forwarded - */ address public feesManager; - - /** - * @notice Maps each bridge's adapter to a PAM - */ - mapping(address => address) adapterToPAM; + mapping(address => address) public adapterToPAM; error OnlyFeesManager(); error UnsufficientAmount(); @@ -50,13 +42,10 @@ contract XERC20 is ERC20, Ownable, IXERC20, ERC20Permit { * * @param _name The name of the token * @param _symbol The symbol of the token + * @param _factory The factory which deployed this contract */ - constructor( - string memory _name, - string memory _symbol, - address /*_factory*/ - ) ERC20(_name, _symbol) ERC20Permit(_name) Ownable(msg.sender) {} + constructor(string memory _name, string memory _symbol, address _factory) ERC20(_name, _symbol) ERC20Permit(_name) Ownable(msg.sender) {} /// @inheritdoc IXERC20 function setFeesManager(address newAddress) public { @@ -78,10 +67,7 @@ contract XERC20 is ERC20, Ownable, IXERC20, ERC20Permit { * @param adapterAddress the adapter address * @param pamAddress the new PAM address */ - function setPAM( - address adapterAddress, - address pamAddress - ) public onlyOwner { + function setPAM(address adapterAddress, address pamAddress) public onlyOwner { adapterToPAM[adapterAddress] = pamAddress; } @@ -151,11 +137,7 @@ contract XERC20 is ERC20, Ownable, IXERC20, ERC20Permit { * @param _burningLimit The updated burning limit we are setting to the bridge * @param _bridge The address of the bridge we are setting the limits too */ - function setLimits( - address _bridge, - uint256 _mintingLimit, - uint256 _burningLimit - ) external onlyOwner { + function setLimits(address _bridge, uint256 _mintingLimit, uint256 _burningLimit) external onlyOwner { _changeMinterLimit(_bridge, _mintingLimit); _changeBurnerLimit(_bridge, _burningLimit); emit BridgeLimitsSet(_mintingLimit, _burningLimit, _bridge); @@ -168,9 +150,7 @@ contract XERC20 is ERC20, Ownable, IXERC20, ERC20Permit { * @return _limit The limit the bridge has */ - function mintingMaxLimitOf( - address _bridge - ) public view returns (uint256 _limit) { + function mintingMaxLimitOf(address _bridge) public view returns (uint256 _limit) { _limit = bridges[_bridge].minterParams.maxLimit; } @@ -181,9 +161,7 @@ contract XERC20 is ERC20, Ownable, IXERC20, ERC20Permit { * @return _limit The limit the bridge has */ - function burningMaxLimitOf( - address _bridge - ) public view returns (uint256 _limit) { + function burningMaxLimitOf(address _bridge) public view returns (uint256 _limit) { _limit = bridges[_bridge].burnerParams.maxLimit; } @@ -194,9 +172,7 @@ contract XERC20 is ERC20, Ownable, IXERC20, ERC20Permit { * @return _limit The limit the bridge has */ - function mintingCurrentLimitOf( - address _bridge - ) public view returns (uint256 _limit) { + function mintingCurrentLimitOf(address _bridge) public view returns (uint256 _limit) { _limit = _getCurrentLimit( bridges[_bridge].minterParams.currentLimit, bridges[_bridge].minterParams.maxLimit, @@ -212,9 +188,7 @@ contract XERC20 is ERC20, Ownable, IXERC20, ERC20Permit { * @return _limit The limit the bridge has */ - function burningCurrentLimitOf( - address _bridge - ) public view returns (uint256 _limit) { + function burningCurrentLimitOf(address _bridge) public view returns (uint256 _limit) { _limit = _getCurrentLimit( bridges[_bridge].burnerParams.currentLimit, bridges[_bridge].burnerParams.maxLimit, @@ -259,11 +233,7 @@ contract XERC20 is ERC20, Ownable, IXERC20, ERC20Permit { uint256 _currentLimit = mintingCurrentLimitOf(_bridge); bridges[_bridge].minterParams.maxLimit = _limit; - bridges[_bridge].minterParams.currentLimit = _calculateNewCurrentLimit( - _limit, - _oldLimit, - _currentLimit - ); + bridges[_bridge].minterParams.currentLimit = _calculateNewCurrentLimit(_limit, _oldLimit, _currentLimit); bridges[_bridge].minterParams.ratePerSecond = _limit / _DURATION; bridges[_bridge].minterParams.timestamp = block.timestamp; @@ -281,11 +251,7 @@ contract XERC20 is ERC20, Ownable, IXERC20, ERC20Permit { uint256 _currentLimit = burningCurrentLimitOf(_bridge); bridges[_bridge].burnerParams.maxLimit = _limit; - bridges[_bridge].burnerParams.currentLimit = _calculateNewCurrentLimit( - _limit, - _oldLimit, - _currentLimit - ); + bridges[_bridge].burnerParams.currentLimit = _calculateNewCurrentLimit(_limit, _oldLimit, _currentLimit); bridges[_bridge].burnerParams.ratePerSecond = _limit / _DURATION; bridges[_bridge].burnerParams.timestamp = block.timestamp; @@ -309,9 +275,7 @@ contract XERC20 is ERC20, Ownable, IXERC20, ERC20Permit { if (_oldLimit > _limit) { _difference = _oldLimit - _limit; - _newCurrentLimit = _currentLimit > _difference - ? _currentLimit - _difference - : 0; + _newCurrentLimit = _currentLimit > _difference ? _currentLimit - _difference : 0; } else { _difference = _limit - _oldLimit; _newCurrentLimit = _currentLimit + _difference; @@ -342,34 +306,20 @@ contract XERC20 is ERC20, Ownable, IXERC20, ERC20Permit { } else if (_timestamp + _DURATION > block.timestamp) { uint256 _timePassed = block.timestamp - _timestamp; uint256 _calculatedLimit = _limit + (_timePassed * _ratePerSecond); - _limit = _calculatedLimit > _maxLimit - ? _maxLimit - : _calculatedLimit; + _limit = _calculatedLimit > _maxLimit ? _maxLimit : _calculatedLimit; } } /** * @notice Internal function for burning tokens * - * @dev Differences from the original xERC20 contract: - * - Fees are taken first - * - Check on the caller's limit on the net amount - * - Burn the net amount for the caller - * * @param _caller The caller address * @param _user The user address * @param _amount The amount to burn */ - function _burnWithCaller( - address _caller, - address _user, - uint256 _amount - ) internal { - uint256 fees = IFeesManager(feesManager).calculateFee( - address(this), - _amount - ); + function _burnWithCaller(address _caller, address _user, uint256 _amount) internal { + uint256 fees = IFeesManager(feesManager).calculateFee(address(this), _amount); if (fees > _amount) revert UnsufficientAmount(); @@ -381,11 +331,7 @@ contract XERC20 is ERC20, Ownable, IXERC20, ERC20Permit { _useBurnerLimits(_caller, netAmount); } - IFeesManager(feesManager).depositFeeFrom( - msg.sender, - address(this), - fees - ); + IFeesManager(feesManager).depositFeeFrom(msg.sender, address(this), fees); _burn(_user, netAmount); } @@ -398,11 +344,7 @@ contract XERC20 is ERC20, Ownable, IXERC20, ERC20Permit { * @param _amount The amount to mint */ - function _mintWithCaller( - address _caller, - address _user, - uint256 _amount - ) internal { + function _mintWithCaller(address _caller, address _user, uint256 _amount) internal { if (_caller != lockbox) { uint256 _currentLimit = mintingCurrentLimitOf(_caller); if (_currentLimit < _amount) revert IXERC20_NotHighEnoughLimits(); diff --git a/solidity/src/test/XERC20Lockbox.sol b/solidity/src/test/XERC20Lockbox.sol index 8e33fc5a..74bc4ccc 100644 --- a/solidity/src/test/XERC20Lockbox.sol +++ b/solidity/src/test/XERC20Lockbox.sol @@ -113,12 +113,6 @@ contract XERC20Lockbox is IXERC20Lockbox { /** * @notice Withdraw tokens from the lockbox - * @dev Different from the original xERC20 Lockbox implementation: - * - We recalculate the fees and compute the net amount - * - We unlock only the net amount - * - * NOTE: the xerc20.burn() function will transfer the fees to the - * feesManager address * * @param _to The user to withdraw to * @param _amount The amount of tokens to withdraw @@ -127,15 +121,11 @@ contract XERC20Lockbox is IXERC20Lockbox { function _withdraw(address _to, uint256 _amount) internal { emit Withdraw(_to, _amount); - IERC20(address(XERC20)).safeTransferFrom( - msg.sender, - address(this), - _amount - ); + IERC20(address(XERC20)).safeTransferFrom(msg.sender, address(this), _amount); // We need to recalculate the net amount here - // otherwise we would burn more than what is - // the msg.sender current balance + // otherwise we would burn more than our current + // balance address feesManager = XERC20.getFeesManager(); uint256 fees = IFeesManager(feesManager).calculateFee( address(XERC20), diff --git a/solidity/src/test/diff-standard.sh b/solidity/src/test/diff-standard.sh new file mode 100755 index 00000000..76ef493c --- /dev/null +++ b/solidity/src/test/diff-standard.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +if [ $# -eq 0 ]; then + echo "Usage: ./$(basename $0) " + exit 1 +fi + +curl -s "https://raw.githubusercontent.com/connext/xERC20/main/solidity/contracts/$1" \ + | sed 's/ / /g' \ + | diff -u --color - "$1" \ No newline at end of file