-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix addition gas in external calls (#195)
* fix contracts * add fallback test * Fix gas addition gas to be 1200 (3500 in total) * Remove gas striction between cross-contract call * remove console * revert garbage
- Loading branch information
Showing
10 changed files
with
178 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.9; | ||
|
||
abstract contract GlobalConfigConsumer { | ||
/// @dev The addition amount of gas sending along in external calls. Total gas stipend is added with default 2300 gas. | ||
uint256 public constant DEFAULT_ADDITION_GAS = 1200; | ||
/// @dev The length of a period in second. | ||
uint256 public constant PERIOD_DURATION = 1 days; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.9; | ||
|
||
import "../extensions/RONTransferHelper.sol"; | ||
|
||
contract MockPaymentFallback { | ||
event SafeReceived(address indexed sender, uint256 value); | ||
|
||
/// @dev Fallback function accepts ether transactions. | ||
receive() external payable { | ||
emit SafeReceived(msg.sender, msg.value); | ||
} | ||
} | ||
|
||
contract MockPaymentFallbackExpensive { | ||
uint[] public array; | ||
event SafeReceived(address indexed sender, uint256 value); | ||
|
||
constructor() { | ||
array.push(0); | ||
} | ||
|
||
/// @dev Fallback function accepts ether transactions and set non-zero value to a zero value slot. | ||
receive() external payable { | ||
array.push(block.number); | ||
emit SafeReceived(msg.sender, msg.value); | ||
} | ||
} | ||
|
||
contract MockTransfer is RONTransferHelper { | ||
uint256 public track; | ||
|
||
constructor() payable {} | ||
|
||
function fooTransfer( | ||
address payable _recipient, | ||
uint256 _amount, | ||
uint256 _gas | ||
) external { | ||
if (_unsafeSendRON(_recipient, _amount, _gas)) { | ||
track++; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
import { expect } from 'chai'; | ||
import { ethers } from 'hardhat'; | ||
import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; | ||
|
||
import { | ||
MockPaymentFallback, | ||
MockPaymentFallbackExpensive, | ||
MockPaymentFallbackExpensive__factory, | ||
MockPaymentFallback__factory, | ||
MockTransfer, | ||
MockTransfer__factory, | ||
} from '../../src/types'; | ||
import { BigNumber } from 'ethers'; | ||
|
||
let senderContract: MockTransfer; | ||
let receiverContract: MockPaymentFallback; | ||
let receiverExpensiveContract: MockPaymentFallbackExpensive; | ||
|
||
let deployer: SignerWithAddress; | ||
let signers: SignerWithAddress[]; | ||
|
||
describe('Payment fallback test', () => { | ||
before(async () => { | ||
[deployer, ...signers] = await ethers.getSigners(); | ||
senderContract = await new MockTransfer__factory(deployer).deploy({ value: 1000 }); | ||
receiverContract = await new MockPaymentFallback__factory(deployer).deploy(); | ||
receiverExpensiveContract = await new MockPaymentFallbackExpensive__factory(deployer).deploy(); | ||
}); | ||
describe('Receiver contract only emit one event in fallback', async () => { | ||
it('Should transfer successfully with 0 gas in addition', async () => { | ||
let value = 1; | ||
let gas = 0; | ||
await expect(senderContract.fooTransfer(receiverContract.address, value, gas)) | ||
.emit(receiverContract, 'SafeReceived') | ||
.withArgs(senderContract.address, value); | ||
}); | ||
it('Should transfer successfully with 2300 gas in addition', async () => { | ||
let value = 1; | ||
let gas = 2300; | ||
await expect(senderContract.fooTransfer(receiverContract.address, value, gas)) | ||
.emit(receiverContract, 'SafeReceived') | ||
.withArgs(senderContract.address, value); | ||
}); | ||
it('Should transfer successfully with 3500 gas in addition', async () => { | ||
let value = 1; | ||
let gas = 3500; | ||
await expect(senderContract.fooTransfer(receiverContract.address, value, gas)) | ||
.emit(receiverContract, 'SafeReceived') | ||
.withArgs(senderContract.address, value); | ||
}); | ||
}); | ||
describe('Receiver contract only emit one event in fallback and set one storage in contract', async () => { | ||
it('Should transfer failed with 0 gas in addition', async () => { | ||
let value = 1; | ||
let gas = 0; | ||
let tx; | ||
await expect( | ||
async () => (tx = await senderContract.fooTransfer(receiverExpensiveContract.address, value, gas)) | ||
).changeEtherBalances([receiverExpensiveContract.address], [BigNumber.from(0)]); | ||
await expect(tx).not.emit(receiverExpensiveContract, 'SafeReceived'); | ||
}); | ||
it('Should transfer failed with 1000 gas in addition', async () => { | ||
let value = 1; | ||
let gas = 1000; | ||
let tx; | ||
await expect( | ||
async () => (tx = await senderContract.fooTransfer(receiverExpensiveContract.address, value, gas)) | ||
).changeEtherBalances([receiverExpensiveContract.address], [BigNumber.from(0)]); | ||
await expect(tx).not.emit(receiverExpensiveContract, 'SafeReceived'); | ||
}); | ||
it('Should transfer failed with 2300 gas in addition', async () => { | ||
let value = 1; | ||
let gas = 2300; | ||
let tx; | ||
await expect( | ||
async () => (tx = await senderContract.fooTransfer(receiverExpensiveContract.address, value, gas)) | ||
).changeEtherBalances([receiverExpensiveContract.address], [BigNumber.from(0)]); | ||
await expect(tx).not.emit(receiverExpensiveContract, 'SafeReceived'); | ||
}); | ||
it('Should transfer failed with 20000 gas in addition', async () => { | ||
let value = 1; | ||
let gas = 20000; | ||
let tx; | ||
await expect( | ||
async () => (tx = await senderContract.fooTransfer(receiverExpensiveContract.address, value, gas)) | ||
).changeEtherBalances([receiverExpensiveContract.address], [BigNumber.from(0)]); | ||
await expect(tx).not.emit(receiverExpensiveContract, 'SafeReceived'); | ||
}); | ||
it('Should transfer successfully with 26000 gas in addition', async () => { | ||
let value = 1; | ||
let gas = 26000; | ||
let tx; | ||
await expect( | ||
async () => (tx = await senderContract.fooTransfer(receiverExpensiveContract.address, value, gas)) | ||
).changeEtherBalances([receiverExpensiveContract.address], [BigNumber.from(1)]); | ||
await expect(tx).emit(receiverExpensiveContract, 'SafeReceived'); | ||
}); | ||
}); | ||
}); |