mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-06-12 23:21:01 +00:00
llvm-context: disable call re-entrancy for send and transfer (#196)
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8;
|
||||
|
||||
/* runner.json
|
||||
{
|
||||
"differential": true,
|
||||
"actions": [
|
||||
{
|
||||
"Upload": {
|
||||
"code": {
|
||||
"Solidity": {
|
||||
"contract": "BalanceReceiver"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Instantiate": {
|
||||
"code": {
|
||||
"Solidity": {
|
||||
"contract": "Balance"
|
||||
}
|
||||
},
|
||||
"value": 24
|
||||
}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "1c8d16b30000000000000000000000000303030303030303030303030303030303030303000000000000000000000000000000000000000000000000000000000000000a"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "6ada15d90000000000000000000000000303030303030303030303030303030303030303000000000000000000000000000000000000000000000000000000000000000a"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
*/
|
||||
|
||||
contract BalanceReceiver {
|
||||
constructor() payable {}
|
||||
|
||||
fallback() external payable {}
|
||||
}
|
||||
|
||||
contract Balance {
|
||||
constructor() payable {
|
||||
// 0 to EOA
|
||||
transfer_to(payable(address(0xdeadbeef)), 0);
|
||||
send_to(payable(address(0xdeadbeef)), 0);
|
||||
|
||||
// 1 to EOA
|
||||
transfer_to(payable(address(0xcafebabe)), 1);
|
||||
send_to(payable(address(0xcafebabe)), 1);
|
||||
|
||||
BalanceReceiver balanceReceiver = new BalanceReceiver();
|
||||
|
||||
// 0 to contract
|
||||
transfer_to(payable(address(balanceReceiver)), 0);
|
||||
send_to(payable(address(balanceReceiver)), 0);
|
||||
|
||||
// 1 to contract
|
||||
transfer_to(payable(address(balanceReceiver)), 1);
|
||||
send_to(payable(address(balanceReceiver)), 1);
|
||||
}
|
||||
|
||||
function transfer_to(address payable _dest, uint _amount) public payable {
|
||||
_dest.transfer(_amount);
|
||||
}
|
||||
|
||||
function send_to(address payable _dest, uint _amount) public payable {
|
||||
require(_dest.send(_amount));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8;
|
||||
|
||||
/* runner.json
|
||||
{
|
||||
"differential": false,
|
||||
"actions": [
|
||||
{
|
||||
"Instantiate": {
|
||||
"code": {
|
||||
"Solidity": {
|
||||
"contract": "Send"
|
||||
}
|
||||
},
|
||||
"value": 211
|
||||
}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "1c8d16b30000000000000000000000000303030303030303030303030303030303030303000000000000000000000000000000000000000000000000000000000000000a"
|
||||
}
|
||||
},
|
||||
{
|
||||
"VerifyCall": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "fb9e8d050000000000000000000000000000000000000000000000000000000000000001"
|
||||
}
|
||||
},
|
||||
{
|
||||
"VerifyCall": {
|
||||
"success": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "fb9e8d050000000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"VerifyCall": {
|
||||
"success": false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
*/
|
||||
|
||||
contract Send {
|
||||
constructor() payable {}
|
||||
|
||||
function transfer_self(uint _amount) public payable {
|
||||
transfer_to(payable(address(this)), _amount);
|
||||
}
|
||||
|
||||
function transfer_to(address payable _dest, uint _amount) public payable {
|
||||
if (_dest.send(_amount)) {}
|
||||
}
|
||||
|
||||
fallback() external {}
|
||||
|
||||
receive() external payable {}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ pragma solidity ^0.8;
|
||||
|
||||
/* runner.json
|
||||
{
|
||||
"differential": true,
|
||||
"differential": false,
|
||||
"actions": [
|
||||
{
|
||||
"Instantiate": {
|
||||
@@ -12,7 +12,7 @@ pragma solidity ^0.8;
|
||||
"contract": "Transfer"
|
||||
}
|
||||
},
|
||||
"value": 11
|
||||
"value": 211
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -23,12 +23,35 @@ pragma solidity ^0.8;
|
||||
"data": "1c8d16b30000000000000000000000000303030303030303030303030303030303030303000000000000000000000000000000000000000000000000000000000000000a"
|
||||
}
|
||||
},
|
||||
{
|
||||
"VerifyCall": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "fb9e8d0500000000000000000000000003030303030303030303030303030303030303030000000000000000000000000000000000000000000000000000000000000001"
|
||||
"data": "fb9e8d050000000000000000000000000000000000000000000000000000000000000001"
|
||||
}
|
||||
},
|
||||
{
|
||||
"VerifyCall": {
|
||||
"success": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "fb9e8d050000000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"VerifyCall": {
|
||||
"success": false
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -36,19 +59,17 @@ pragma solidity ^0.8;
|
||||
*/
|
||||
|
||||
contract Transfer {
|
||||
constructor() payable {
|
||||
transfer_self(msg.value);
|
||||
}
|
||||
|
||||
function address_self() internal view returns (address payable) {
|
||||
return payable(address(this));
|
||||
}
|
||||
constructor() payable {}
|
||||
|
||||
function transfer_self(uint _amount) public payable {
|
||||
transfer_to(address_self(), _amount);
|
||||
transfer_to(payable(address(this)), _amount);
|
||||
}
|
||||
|
||||
function transfer_to(address payable _dest, uint _amount) public payable {
|
||||
_dest.transfer(_amount);
|
||||
}
|
||||
|
||||
fallback() external {}
|
||||
|
||||
receive() external payable {}
|
||||
}
|
||||
|
||||
@@ -156,6 +156,20 @@ case!("DivisionArithmetics.sol", DivisionArithmetics, sdivCall, division_arithme
|
||||
case!("DivisionArithmetics.sol", DivisionArithmetics, modCall, division_arithmetics_mod, n: U256, d: U256);
|
||||
case!("DivisionArithmetics.sol", DivisionArithmetics, smodCall, division_arithmetics_smod, n: I256, d: I256);
|
||||
|
||||
sol!(
|
||||
contract Send {
|
||||
function transfer_self(uint _amount) public payable;
|
||||
}
|
||||
);
|
||||
case!("Send.sol", Send, transfer_selfCall, send_self, amount: U256);
|
||||
|
||||
sol!(
|
||||
contract Transfer {
|
||||
function transfer_self(uint _amount) public payable;
|
||||
}
|
||||
);
|
||||
case!("Transfer.sol", Transfer, transfer_selfCall, transfer_self, amount: U256);
|
||||
|
||||
sol!(
|
||||
contract MStore8 {
|
||||
function mStore8(uint value) public pure returns (uint256 word);
|
||||
|
||||
@@ -37,10 +37,10 @@ test_spec!(events, "Events", "Events.sol");
|
||||
test_spec!(storage, "Storage", "Storage.sol");
|
||||
test_spec!(mstore8, "MStore8", "MStore8.sol");
|
||||
test_spec!(address, "Context", "Context.sol");
|
||||
test_spec!(balance, "Value", "Value.sol");
|
||||
test_spec!(value, "Value", "Value.sol");
|
||||
test_spec!(create, "CreateB", "Create.sol");
|
||||
test_spec!(call, "Caller", "Call.sol");
|
||||
test_spec!(transfer, "Transfer", "Transfer.sol");
|
||||
test_spec!(balance, "Balance", "Balance.sol");
|
||||
test_spec!(return_data_oob, "ReturnDataOob", "ReturnDataOob.sol");
|
||||
test_spec!(immutables, "Immutables", "Immutables.sol");
|
||||
test_spec!(transaction, "Transaction", "Transaction.sol");
|
||||
@@ -52,6 +52,8 @@ test_spec!(gas_limit, "GasLimit", "GasLimit.sol");
|
||||
test_spec!(base_fee, "BaseFee", "BaseFee.sol");
|
||||
test_spec!(coinbase, "Coinbase", "Coinbase.sol");
|
||||
test_spec!(create2, "CreateB", "Create2.sol");
|
||||
test_spec!(transfer, "Transfer", "Transfer.sol");
|
||||
test_spec!(send, "Send", "Send.sol");
|
||||
|
||||
fn instantiate(path: &str, contract: &str) -> Vec<SpecsAction> {
|
||||
vec![Instantiate {
|
||||
@@ -434,3 +436,47 @@ fn ext_code_size() {
|
||||
}
|
||||
.run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "ReentranceDenied")]
|
||||
fn send_denies_reentrancy() {
|
||||
let value = 1000;
|
||||
Specs {
|
||||
actions: vec![
|
||||
instantiate("contracts/Send.sol", "Send").remove(0),
|
||||
Call {
|
||||
origin: TestAddress::Alice,
|
||||
dest: TestAddress::Instantiated(0),
|
||||
value,
|
||||
gas_limit: None,
|
||||
storage_deposit_limit: None,
|
||||
data: Contract::send_self(U256::from(value)).calldata,
|
||||
},
|
||||
],
|
||||
differential: false,
|
||||
..Default::default()
|
||||
}
|
||||
.run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "ReentranceDenied")]
|
||||
fn transfer_denies_reentrancy() {
|
||||
let value = 1000;
|
||||
Specs {
|
||||
actions: vec![
|
||||
instantiate("contracts/Transfer.sol", "Transfer").remove(0),
|
||||
Call {
|
||||
origin: TestAddress::Alice,
|
||||
dest: TestAddress::Instantiated(0),
|
||||
value,
|
||||
gas_limit: None,
|
||||
storage_deposit_limit: None,
|
||||
data: Contract::transfer_self(U256::from(value)).calldata,
|
||||
},
|
||||
],
|
||||
differential: false,
|
||||
..Default::default()
|
||||
}
|
||||
.run();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user