diff --git a/contracts/ito.sol b/contracts/ito.sol index 326caf8..2035abc 100644 --- a/contracts/ito.sol +++ b/contracts/ito.sol @@ -227,6 +227,7 @@ contract HappyTokenPool is Initializable { ) public payable returns (uint256 swapped) { + require(tx.origin == msg.sender, "not real user"); uint128 from_value = input_total; Pool storage pool = pool_by_id[id]; Packed1 memory packed1 = pool.packed1; diff --git a/contracts/test/MultiCall.sol b/contracts/test/MultiCall.sol new file mode 100644 index 0000000..6b39bf8 --- /dev/null +++ b/contracts/test/MultiCall.sol @@ -0,0 +1,23 @@ +pragma solidity >=0.5.0; + +import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; + +contract Multicall is IERC721Receiver { + struct Call { + address target; + bytes callData; + uint256 value; + } + + function aggregate(Call[] memory calls) external payable { + for(uint256 i = 0; i < calls.length; i++) { + (bool success, bytes memory ret) = calls[i].target.call{ value: calls[i].value}(calls[i].callData); + require(success, "Multicall: call failed"); + } + } + + function onERC721Received(address, address, uint256, bytes calldata) + public override pure returns(bytes4) { + return this.onERC721Received.selector; + } +} diff --git a/contracts/test_tokenA.sol b/contracts/test/test_tokenA.sol similarity index 100% rename from contracts/test_tokenA.sol rename to contracts/test/test_tokenA.sol diff --git a/contracts/test_tokenB.sol b/contracts/test/test_tokenB.sol similarity index 100% rename from contracts/test_tokenB.sol rename to contracts/test/test_tokenB.sol diff --git a/contracts/test_tokenC.sol b/contracts/test/test_tokenC.sol similarity index 100% rename from contracts/test_tokenC.sol rename to contracts/test/test_tokenC.sol diff --git a/test/TestTP.js b/test/TestTP.js index 2282e9d..3c6de4f 100644 --- a/test/TestTP.js +++ b/test/TestTP.js @@ -34,6 +34,7 @@ let snapshotId; let testTokenADeployed; let testTokenBDeployed; let testTokenCDeployed; +let multiCallContract; let HappyTokenPool; let happyTokenPoolDeployed; @@ -70,6 +71,11 @@ describe('HappyTokenPool', () => { HappyTokenPool = await ethers.getContractFactory('HappyTokenPool'); HappyTokenPoolProxy = await upgrades.deployProxy(HappyTokenPool, [base_timestamp]); happyTokenPoolDeployed = new ethers.Contract(HappyTokenPoolProxy.address, itoJsonABI.abi, creator); + { + const factory = await ethers.getContractFactory('Multicall'); + const nContract = await factory.deploy(); + multiCallContract = await nContract.deployed(); + } }); beforeEach(async () => { @@ -681,6 +687,31 @@ describe('HappyTokenPool', () => { } }); + it('Should swap tx from contracts not work', async () => { + fpp.total_tokens = BigNumber('100e18').toFixed(); + fpp.limit = BigNumber('50e18').toFixed(); + const { id: pool_id } = await getResultFromPoolFill(happyTokenPoolDeployed, fpp); + + // 0.004 ETH => 40 TESTA + approve_amount = BigNumber('4e15').toFixed(); + exchange_amount = approve_amount; + var vr = getVerification(PASSWORD, multiCallContract.address); + const encodedSwapData = itoInterface.encodeFunctionData('swap', [ + pool_id, + vr.verification, + 0, + exchange_amount, + [pool_id], + ]); + await expect( + multiCallContract + .connect(signers[4]) + .aggregate([[happyTokenPoolDeployed.address, encodedSwapData, approve_amount]], { + value: approve_amount, + }), + ).to.be.rejectedWith('Multicall: call failed'); + }); + it('Should swap the remaining token when the amount of swap token is greater than total token', async () => { const ratio = 10 ** 10; fpp.exchange_ratios = [1, ratio];