diff --git a/contracts/common/tokens/POLTokenMock.sol b/contracts/common/tokens/POLTokenMock.sol new file mode 100644 index 00000000..c666f98a --- /dev/null +++ b/contracts/common/tokens/POLTokenMock.sol @@ -0,0 +1,56 @@ +pragma solidity ^0.5.2; + +import "openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol"; +import "openzeppelin-solidity/contracts/utils/Address.sol"; + + +contract POLTokenMock is ERC20Mintable { + using Address for address; + + // detailed ERC20 + string public name; + string public symbol; + uint8 public decimals = 18; + + constructor(string memory _name, string memory _symbol) public { + name = _name; + symbol = _symbol; + + uint256 value = 10**10 * (10**18); + mint(msg.sender, value); + } + + function safeTransfer(IERC20 token, address to, uint256 value) public { + callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); + } + + function safeTransferFrom(IERC20 token, address from, address to, uint256 value) public { + callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); + } + + /** + * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement + * on the return value: the return value is optional (but if data is returned, it must equal true). + * @param token The token targeted by the call. + * @param data The call data (encoded using abi.encode or one of its variants). + */ + function callOptionalReturn(IERC20 token, bytes memory data) private { + // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since + // we're implementing it ourselves. + + // A Solidity high level call has three parts: + // 1. The target address is checked to verify it contains contract code + // 2. The call itself is made, and success asserted + // 3. The return value is decoded, which in turn checks the size of the returned data. + + require(address(token).isContract()); + + // solhint-disable-next-line avoid-low-level-calls + (bool success, bytes memory returndata) = address(token).call(data); + require(success); + + if (returndata.length > 0) { // Return data is optional + require(abi.decode(returndata, (bool))); + } + } +} diff --git a/contracts/common/tokens/TestToken.sol b/contracts/common/tokens/TestToken.sol index 7996ee73..7dffc006 100644 --- a/contracts/common/tokens/TestToken.sol +++ b/contracts/common/tokens/TestToken.sol @@ -1,11 +1,8 @@ pragma solidity ^0.5.2; import "openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol"; -import "openzeppelin-solidity/contracts/utils/Address.sol"; contract TestToken is ERC20Mintable { - using Address for address; - // detailed ERC20 string public name; string public symbol; @@ -18,38 +15,4 @@ contract TestToken is ERC20Mintable { uint256 value = 10**10 * (10**18); mint(msg.sender, value); } - - function safeTransfer(IERC20 token, address to, uint256 value) public { - callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); - } - - function safeTransferFrom(IERC20 token, address from, address to, uint256 value) public { - callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); - } - - /** - * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement - * on the return value: the return value is optional (but if data is returned, it must equal true). - * @param token The token targeted by the call. - * @param data The call data (encoded using abi.encode or one of its variants). - */ - function callOptionalReturn(IERC20 token, bytes memory data) private { - // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since - // we're implementing it ourselves. - - // A Solidity high level call has three parts: - // 1. The target address is checked to verify it contains contract code - // 2. The call itself is made, and success asserted - // 3. The return value is decoded, which in turn checks the size of the returned data. - - require(address(token).isContract()); - - // solhint-disable-next-line avoid-low-level-calls - (bool success, bytes memory returndata) = address(token).call(data); - require(success); - - if (returndata.length > 0) { // Return data is optional - require(abi.decode(returndata, (bool))); - } - } } diff --git a/test/helpers/artifacts.js b/test/helpers/artifacts.js index 2226128d..fe9fe25b 100644 --- a/test/helpers/artifacts.js +++ b/test/helpers/artifacts.js @@ -44,6 +44,7 @@ export const TransferWithSigPredicate = artifacts.require( // tokens export const MaticWETH = artifacts.require('MaticWETH') +export const POLTokenMock = artifacts.require('POLTokenMock') export const TestToken = artifacts.require('TestToken') export const RootERC721 = artifacts.require('RootERC721') export const ERC721PlasmaMintable = artifacts.require('ERC721PlasmaMintable') diff --git a/test/integration/root/DepositManagerUpdate.test.js b/test/integration/root/DepositManagerUpdate.test.js index 4b2c30ee..c13e2f21 100644 --- a/test/integration/root/DepositManagerUpdate.test.js +++ b/test/integration/root/DepositManagerUpdate.test.js @@ -44,7 +44,7 @@ contract('DepositManager Update @skip-on-coverage', async function(accounts) { registry.contract.methods.updateContractMap(ethUtils.keccak256('polygonMigration'), polygonMigrationTest.address).encodeABI() ) - pol = await artifacts.TestToken.new('Polygon Ecosystem Token', 'POL') + pol = await artifacts.POLTokenMock.new('Polygon Ecosystem Token', 'POL') await governance.update( registry.address,