mirror of https://github.com/vacp2p/minime.git
add approve and call test
This commit is contained in:
parent
16d3feb5d9
commit
6cf3528f01
|
@ -3,9 +3,10 @@
|
||||||
| Deployment Cost | Deployment Size | | | | |
|
| Deployment Cost | Deployment Size | | | | |
|
||||||
| 1788057 | 9919 | | | | |
|
| 1788057 | 9919 | | | | |
|
||||||
| Function Name | min | avg | median | max | # calls |
|
| Function Name | min | avg | median | max | # calls |
|
||||||
| allowance | 0 | 80 | 0 | 808 | 10 |
|
| allowance | 0 | 67 | 0 | 808 | 12 |
|
||||||
| approve | 0 | 15995 | 23208 | 31708 | 9 |
|
| approve | 0 | 15995 | 23208 | 31708 | 9 |
|
||||||
| balanceOf | 0 | 355 | 0 | 2753 | 41 |
|
| approveAndCall | 0 | 31199 | 0 | 93597 | 3 |
|
||||||
|
| balanceOf | 0 | 323 | 0 | 2753 | 45 |
|
||||||
| balanceOfAt | 0 | 90 | 0 | 2363 | 26 |
|
| balanceOfAt | 0 | 90 | 0 | 2363 | 26 |
|
||||||
| changeController | 0 | 1014 | 758 | 3558 | 5 |
|
| changeController | 0 | 1014 | 758 | 3558 | 5 |
|
||||||
| claimTokens | 9537 | 41277 | 57148 | 57148 | 3 |
|
| claimTokens | 9537 | 41277 | 57148 | 57148 | 3 |
|
||||||
|
@ -14,7 +15,7 @@
|
||||||
| decimals | 0 | 0 | 0 | 0 | 7 |
|
| decimals | 0 | 0 | 0 | 0 | 7 |
|
||||||
| destroyTokens | 8956 | 8956 | 8956 | 8956 | 1 |
|
| destroyTokens | 8956 | 8956 | 8956 | 8956 | 1 |
|
||||||
| enableTransfers | 0 | 0 | 0 | 0 | 3 |
|
| enableTransfers | 0 | 0 | 0 | 0 | 3 |
|
||||||
| generateTokens | 0 | 9264 | 0 | 95751 | 31 |
|
| generateTokens | 0 | 8974 | 0 | 95751 | 32 |
|
||||||
| name | 0 | 0 | 0 | 0 | 7 |
|
| name | 0 | 0 | 0 | 0 | 7 |
|
||||||
| parentSnapShotBlock | 0 | 0 | 0 | 0 | 8 |
|
| parentSnapShotBlock | 0 | 0 | 0 | 0 | 8 |
|
||||||
| parentToken | 0 | 0 | 0 | 0 | 8 |
|
| parentToken | 0 | 0 | 0 | 0 | 8 |
|
||||||
|
@ -22,7 +23,7 @@
|
||||||
| totalSupply | 0 | 273 | 0 | 1911 | 7 |
|
| totalSupply | 0 | 273 | 0 | 1911 | 7 |
|
||||||
| totalSupplyAt | 0 | 285 | 0 | 1995 | 7 |
|
| totalSupplyAt | 0 | 285 | 0 | 1995 | 7 |
|
||||||
| transfer | 526 | 36631 | 40486 | 75187 | 16 |
|
| transfer | 526 | 36631 | 40486 | 75187 | 16 |
|
||||||
| transferFrom | 0 | 15187 | 3495 | 66590 | 5 |
|
| transferFrom | 0 | 16836 | 3495 | 66590 | 7 |
|
||||||
|
|
||||||
|
|
||||||
| contracts/MiniMeTokenFactory.sol:MiniMeTokenFactory contract | | | | | |
|
| contracts/MiniMeTokenFactory.sol:MiniMeTokenFactory contract | | | | | |
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
AllowanceTest:testAllowance() (gas: 42696)
|
AllowanceTest:testAllowance() (gas: 42689)
|
||||||
AllowanceTest:testAllowanceAlreadySet() (gas: 36779)
|
AllowanceTest:testAllowanceAlreadySet() (gas: 36809)
|
||||||
AllowanceTest:testAllowanceReset() (gas: 45888)
|
AllowanceTest:testAllowanceReset() (gas: 45943)
|
||||||
AllowanceTest:testApproveTransferDisabled() (gas: 7975)
|
AllowanceTest:testApproveAndCall() (gas: 98516)
|
||||||
AllowanceTest:testDeployment() (gas: 26617)
|
AllowanceTest:testApproveTransferDisabled() (gas: 7968)
|
||||||
AllowanceTest:testNoAllowance() (gas: 9469)
|
AllowanceTest:testDeployment() (gas: 26711)
|
||||||
|
AllowanceTest:testNoAllowance() (gas: 9462)
|
||||||
ClaimTokensTest:testClaimERC20() (gas: 63734)
|
ClaimTokensTest:testClaimERC20() (gas: 63734)
|
||||||
ClaimTokensTest:testClaimETH() (gas: 13637)
|
ClaimTokensTest:testClaimETH() (gas: 13637)
|
||||||
ClaimTokensTest:testClaimSelf() (gas: 61216)
|
ClaimTokensTest:testClaimSelf() (gas: 61216)
|
||||||
|
|
|
@ -12,9 +12,11 @@ import {
|
||||||
InvalidDestination,
|
InvalidDestination,
|
||||||
NotEnoughBalance,
|
NotEnoughBalance,
|
||||||
NotEnoughAllowance,
|
NotEnoughAllowance,
|
||||||
AllowanceAlreadySet
|
AllowanceAlreadySet,
|
||||||
|
IERC20
|
||||||
} from "../contracts/MiniMeToken.sol";
|
} from "../contracts/MiniMeToken.sol";
|
||||||
import { MiniMeTokenFactory } from "../contracts/MiniMeTokenFactory.sol";
|
import { MiniMeTokenFactory } from "../contracts/MiniMeTokenFactory.sol";
|
||||||
|
import { ApproveAndCallFallBack } from "../contracts/ApproveAndCallFallBack.sol";
|
||||||
|
|
||||||
contract MiniMeTokenTest is Test {
|
contract MiniMeTokenTest is Test {
|
||||||
DeploymentConfig internal deploymentConfig;
|
DeploymentConfig internal deploymentConfig;
|
||||||
|
@ -375,6 +377,165 @@ contract AllowanceTest is MiniMeTokenTest {
|
||||||
assertEq(minimeToken.allowance(accounts[0], accounts[1]), 3, "allowance should be 3");
|
assertEq(minimeToken.allowance(accounts[0], accounts[1]), 3, "allowance should be 3");
|
||||||
vm.resumeGasMetering();
|
vm.resumeGasMetering();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testApproveAndCall() public {
|
||||||
|
vm.pauseGasMetering();
|
||||||
|
_generateTokens(accounts[0], 10);
|
||||||
|
ApproverAccount approverAccount = new ApproverAccount(minimeToken);
|
||||||
|
vm.startPrank(accounts[0]);
|
||||||
|
vm.resumeGasMetering();
|
||||||
|
minimeToken.approveAndCall(
|
||||||
|
address(approverAccount), 2, abi.encodeWithSelector(approverAccount.depositToken1.selector, "message", 123)
|
||||||
|
);
|
||||||
|
vm.pauseGasMetering();
|
||||||
|
assertEq(minimeToken.allowance(accounts[0], address(approverAccount)), 0, "allowance should be 0");
|
||||||
|
assertEq(minimeToken.balanceOf(address(approverAccount)), 2, "approverAccount should have 2 tokens");
|
||||||
|
assertEq(minimeToken.balanceOf(accounts[0]), 8, "balance of sender should be reduced");
|
||||||
|
assertEq(approverAccount.message(), "message", "message should be correct");
|
||||||
|
minimeToken.approveAndCall(
|
||||||
|
address(approverAccount), 2, abi.encodeWithSelector(approverAccount.depositToken2.selector, true, "data")
|
||||||
|
);
|
||||||
|
assertEq(minimeToken.allowance(accounts[0], address(approverAccount)), 0, "allowance should be 0");
|
||||||
|
assertEq(minimeToken.balanceOf(address(approverAccount)), 4, "approverAccount should have 2 tokens");
|
||||||
|
assertEq(minimeToken.balanceOf(accounts[0]), 6, "balance of sender should be reduced");
|
||||||
|
assertEq(approverAccount.data(), "data", "data should be correct");
|
||||||
|
vm.expectRevert("ApproverAccount: invalid method");
|
||||||
|
minimeToken.approveAndCall(
|
||||||
|
address(approverAccount),
|
||||||
|
2,
|
||||||
|
abi.encodeWithSelector(approverAccount.unsupportedMethod.selector, true, "data")
|
||||||
|
);
|
||||||
|
vm.stopPrank();
|
||||||
|
vm.resumeGasMetering();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contract ApproverAccount is ApproveAndCallFallBack {
|
||||||
|
IERC20 public token;
|
||||||
|
|
||||||
|
string public message;
|
||||||
|
bytes public data;
|
||||||
|
|
||||||
|
constructor(IERC20 _token) {
|
||||||
|
token = _token;
|
||||||
|
}
|
||||||
|
|
||||||
|
event ApprovalReceived(address _from, uint256 _amount, address _token, bytes _data);
|
||||||
|
event TokenDeposit1(address indexed _from, uint256 _amount, string _message, uint256 _number);
|
||||||
|
event TokenDeposit2(address indexed _from, uint256 _amount, bool _value, bytes _data);
|
||||||
|
|
||||||
|
function receiveApproval(address _from, uint256 _amount, address _token, bytes memory _data) public override {
|
||||||
|
emit ApprovalReceived(_from, _amount, _token, _data);
|
||||||
|
require(_token == address(token), "ApproverAccount: token is not correct");
|
||||||
|
bytes4 sig = abiDecodeSig(_data);
|
||||||
|
bytes memory cdata = slice(_data, 4, _data.length - 4);
|
||||||
|
if (sig == this.depositToken1.selector) {
|
||||||
|
(string memory _message, uint256 _number) = abi.decode(cdata, (string, uint256));
|
||||||
|
depositToken1(_from, _amount, _message, _number);
|
||||||
|
} else if (sig == this.depositToken2.selector) {
|
||||||
|
(bool _value, bytes memory _decodedData) = abi.decode(cdata, (bool, bytes));
|
||||||
|
depositToken2(_from, _amount, _value, _decodedData);
|
||||||
|
} else {
|
||||||
|
revert("ApproverAccount: invalid method");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function depositToken1(string memory _message, uint256 _number) external {
|
||||||
|
depositToken1(msg.sender, token.allowance(msg.sender, address(this)), _message, _number);
|
||||||
|
}
|
||||||
|
|
||||||
|
function depositToken2(bool _value, bytes memory _data) external {
|
||||||
|
depositToken2(msg.sender, token.allowance(msg.sender, address(this)), _value, _data);
|
||||||
|
}
|
||||||
|
|
||||||
|
function depositToken1(address _from, uint256 _amount, string memory _message, uint256 _number) internal {
|
||||||
|
IERC20(token).transferFrom(_from, address(this), _amount);
|
||||||
|
message = _message;
|
||||||
|
emit TokenDeposit1(_from, _amount, _message, _number);
|
||||||
|
}
|
||||||
|
|
||||||
|
function depositToken2(address _from, uint256 _amount, bool _value, bytes memory _data) internal {
|
||||||
|
IERC20(token).transferFrom(_from, address(this), _amount);
|
||||||
|
data = _data;
|
||||||
|
emit TokenDeposit2(_from, _amount, _value, _data);
|
||||||
|
}
|
||||||
|
|
||||||
|
function unsupportedMethod() external {
|
||||||
|
revert("ApproverAccount: unsupported method");
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @dev decodes sig of abi encoded call
|
||||||
|
* @param _data abi encoded data
|
||||||
|
* @return sig (first 4 bytes)
|
||||||
|
*/
|
||||||
|
|
||||||
|
function abiDecodeSig(bytes memory _data) private pure returns (bytes4 sig) {
|
||||||
|
assembly {
|
||||||
|
sig := mload(add(_data, add(0x20, 0)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev get a slice of byte array
|
||||||
|
* @param _bytes source
|
||||||
|
* @param _start pointer
|
||||||
|
* @param _length size to read
|
||||||
|
* @return sliced bytes
|
||||||
|
*/
|
||||||
|
function slice(bytes memory _bytes, uint256 _start, uint256 _length) private pure returns (bytes memory) {
|
||||||
|
require(_bytes.length >= (_start + _length));
|
||||||
|
|
||||||
|
bytes memory tempBytes;
|
||||||
|
|
||||||
|
assembly {
|
||||||
|
switch iszero(_length)
|
||||||
|
case 0 {
|
||||||
|
// Get a location of some free memory and store it in tempBytes as
|
||||||
|
// Solidity does for memory variables.
|
||||||
|
tempBytes := mload(0x40)
|
||||||
|
|
||||||
|
// The first word of the slice result is potentially a partial
|
||||||
|
// word read from the original array. To read it, we calculate
|
||||||
|
// the length of that partial word and start copying that many
|
||||||
|
// bytes into the array. The first word we copy will start with
|
||||||
|
// data we don't care about, but the last `lengthmod` bytes will
|
||||||
|
// land at the beginning of the contents of the new array. When
|
||||||
|
// we're done copying, we overwrite the full first word with
|
||||||
|
// the actual length of the slice.
|
||||||
|
let lengthmod := and(_length, 31)
|
||||||
|
|
||||||
|
// The multiplication in the next line is necessary
|
||||||
|
// because when slicing multiples of 32 bytes (lengthmod == 0)
|
||||||
|
// the following copy loop was copying the origin's length
|
||||||
|
// and then ending prematurely not copying everything it should.
|
||||||
|
let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))
|
||||||
|
let end := add(mc, _length)
|
||||||
|
|
||||||
|
for {
|
||||||
|
// The multiplication in the next line has the same exact purpose
|
||||||
|
// as the one above.
|
||||||
|
let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)
|
||||||
|
} lt(mc, end) {
|
||||||
|
mc := add(mc, 0x20)
|
||||||
|
cc := add(cc, 0x20)
|
||||||
|
} { mstore(mc, mload(cc)) }
|
||||||
|
|
||||||
|
mstore(tempBytes, _length)
|
||||||
|
|
||||||
|
//update free-memory pointer
|
||||||
|
//allocating the array padded to 32 bytes like the compiler does now
|
||||||
|
mstore(0x40, and(add(mc, 31), not(31)))
|
||||||
|
}
|
||||||
|
//if we want a zero-length slice let's just return a zero-length array
|
||||||
|
default {
|
||||||
|
tempBytes := mload(0x40)
|
||||||
|
|
||||||
|
mstore(0x40, add(tempBytes, 0x20))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tempBytes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
contract DestroyTokensTest is MiniMeTokenTest {
|
contract DestroyTokensTest is MiniMeTokenTest {
|
||||||
|
|
Loading…
Reference in New Issue