Skip to content

Commit

Permalink
test: add TestDirtyStateAttack3
Browse files Browse the repository at this point in the history
  • Loading branch information
k-yang committed Jan 22, 2025
1 parent dfe0f08 commit 19db354
Show file tree
Hide file tree
Showing 4 changed files with 221 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"_format": "hh-sol-artifact-1",
"contractName": "TestDirtyStateAttack3",
"sourceName": "contracts/TestDirtyStateAttack3.sol",
"abi": [
{
"inputs": [
{
"internalType": "address",
"name": "erc20_",
"type": "address"
}
],
"stateMutability": "payable",
"type": "constructor"
},
{
"inputs": [
{
"internalType": "address payable",
"name": "sendRecipient",
"type": "address"
},
{
"internalType": "string",
"name": "bech32Recipient",
"type": "string"
}
],
"name": "attack",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address payable",
"name": "sendRecipient",
"type": "address"
},
{
"internalType": "string",
"name": "bech32Recipient",
"type": "string"
}
],
"name": "transferFunds",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
],
"bytecode": "0x6080604052600060015560405161094c38038061094c833981810160405281019061002a91906100d3565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050610100565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100a082610075565b9050919050565b6100b081610095565b81146100bb57600080fd5b50565b6000815190506100cd816100a7565b92915050565b6000602082840312156100e9576100e8610070565b5b60006100f7848285016100be565b91505092915050565b61083d8061010f6000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80631054aea21461003b578063e655beb414610057575b600080fd5b610055600480360381019061005091906104d3565b610073565b005b610071600480360381019061006c91906104d3565b610277565b005b8173ffffffffffffffffffffffffffffffffffffffff166108fc678ac7230489e800009081150290604051600060405180830381858888f193505050506100ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100e69061058c565b60405180910390fd5b600061080073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff16629896808460405160240161014293929190610654565b6040516020818303038152906040527fe77a47bf000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516101cc91906106d9565b6000604051808303816000865af19150503d8060008114610209576040519150601f19603f3d011682016040523d82523d6000602084013e61020e565b606091505b505090508060405160200161022290610716565b60405160208183030381529060405290610272576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610269919061072f565b60405180910390fd5b600080fd5b6001600081548092919061028a90610780565b91905055503073ffffffffffffffffffffffffffffffffffffffff16631054aea283836040518363ffffffff1660e01b81526004016102ca9291906107d7565b600060405180830381600087803b1580156102e457600080fd5b505af19250505080156102f5575060015b610316576001600081548092919061030c90610780565b9190505550610317565b5b5050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061035a8261032f565b9050919050565b61036a8161034f565b811461037557600080fd5b50565b60008135905061038781610361565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6103e082610397565b810181811067ffffffffffffffff821117156103ff576103fe6103a8565b5b80604052505050565b600061041261031b565b905061041e82826103d7565b919050565b600067ffffffffffffffff82111561043e5761043d6103a8565b5b61044782610397565b9050602081019050919050565b82818337600083830152505050565b600061047661047184610423565b610408565b90508281526020810184848401111561049257610491610392565b5b61049d848285610454565b509392505050565b600082601f8301126104ba576104b961038d565b5b81356104ca848260208601610463565b91505092915050565b600080604083850312156104ea576104e9610325565b5b60006104f885828601610378565b925050602083013567ffffffffffffffff8111156105195761051861032a565b5b610525858286016104a5565b9150509250929050565b600082825260208201905092915050565b7f455448207472616e73666572206661696c656400000000000000000000000000600082015250565b600061057660138361052f565b915061058182610540565b602082019050919050565b600060208201905081810360008301526105a581610569565b9050919050565b60006105b78261032f565b9050919050565b6105c7816105ac565b82525050565b6000819050919050565b6105e0816105cd565b82525050565b600081519050919050565b60005b8381101561060f5780820151818401526020810190506105f4565b60008484015250505050565b6000610626826105e6565b610630818561052f565b93506106408185602086016105f1565b61064981610397565b840191505092915050565b600060608201905061066960008301866105be565b61067660208301856105d7565b8181036040830152610688818461061b565b9050949350505050565b600081519050919050565b600081905092915050565b60006106b382610692565b6106bd818561069d565b93506106cd8185602086016105f1565b80840191505092915050565b60006106e582846106a8565b915081905092915050565b7f4661696c656420746f2063616c6c2062616e6b53656e64000000000000000000815250565b6000610721826106f0565b601782019150819050919050565b60006020820190508181036000830152610749818461061b565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061078b826105cd565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036107bd576107bc610751565b5b600182019050919050565b6107d18161034f565b82525050565b60006040820190506107ec60008301856107c8565b81810360208301526107fe818461061b565b9050939250505056fea2646970667358221220c3d57175350dbc81f4b427386910dce09422042c0b464bd34bfcdb6940a4715964736f6c63430008180033",
"deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80631054aea21461003b578063e655beb414610057575b600080fd5b610055600480360381019061005091906104d3565b610073565b005b610071600480360381019061006c91906104d3565b610277565b005b8173ffffffffffffffffffffffffffffffffffffffff166108fc678ac7230489e800009081150290604051600060405180830381858888f193505050506100ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100e69061058c565b60405180910390fd5b600061080073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff16629896808460405160240161014293929190610654565b6040516020818303038152906040527fe77a47bf000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516101cc91906106d9565b6000604051808303816000865af19150503d8060008114610209576040519150601f19603f3d011682016040523d82523d6000602084013e61020e565b606091505b505090508060405160200161022290610716565b60405160208183030381529060405290610272576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610269919061072f565b60405180910390fd5b600080fd5b6001600081548092919061028a90610780565b91905055503073ffffffffffffffffffffffffffffffffffffffff16631054aea283836040518363ffffffff1660e01b81526004016102ca9291906107d7565b600060405180830381600087803b1580156102e457600080fd5b505af19250505080156102f5575060015b610316576001600081548092919061030c90610780565b9190505550610317565b5b5050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061035a8261032f565b9050919050565b61036a8161034f565b811461037557600080fd5b50565b60008135905061038781610361565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6103e082610397565b810181811067ffffffffffffffff821117156103ff576103fe6103a8565b5b80604052505050565b600061041261031b565b905061041e82826103d7565b919050565b600067ffffffffffffffff82111561043e5761043d6103a8565b5b61044782610397565b9050602081019050919050565b82818337600083830152505050565b600061047661047184610423565b610408565b90508281526020810184848401111561049257610491610392565b5b61049d848285610454565b509392505050565b600082601f8301126104ba576104b961038d565b5b81356104ca848260208601610463565b91505092915050565b600080604083850312156104ea576104e9610325565b5b60006104f885828601610378565b925050602083013567ffffffffffffffff8111156105195761051861032a565b5b610525858286016104a5565b9150509250929050565b600082825260208201905092915050565b7f455448207472616e73666572206661696c656400000000000000000000000000600082015250565b600061057660138361052f565b915061058182610540565b602082019050919050565b600060208201905081810360008301526105a581610569565b9050919050565b60006105b78261032f565b9050919050565b6105c7816105ac565b82525050565b6000819050919050565b6105e0816105cd565b82525050565b600081519050919050565b60005b8381101561060f5780820151818401526020810190506105f4565b60008484015250505050565b6000610626826105e6565b610630818561052f565b93506106408185602086016105f1565b61064981610397565b840191505092915050565b600060608201905061066960008301866105be565b61067660208301856105d7565b8181036040830152610688818461061b565b9050949350505050565b600081519050919050565b600081905092915050565b60006106b382610692565b6106bd818561069d565b93506106cd8185602086016105f1565b80840191505092915050565b60006106e582846106a8565b915081905092915050565b7f4661696c656420746f2063616c6c2062616e6b53656e64000000000000000000815250565b6000610721826106f0565b601782019150819050919050565b60006020820190508181036000830152610749818461061b565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061078b826105cd565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036107bd576107bc610751565b5b600182019050919050565b6107d18161034f565b82525050565b60006040820190506107ec60008301856107c8565b81810360208301526107fe818461061b565b9050939250505056fea2646970667358221220c3d57175350dbc81f4b427386910dce09422042c0b464bd34bfcdb6940a4715964736f6c63430008180033",
"linkReferences": {},
"deployedLinkReferences": {}
}
53 changes: 53 additions & 0 deletions x/evm/embeds/contracts/TestDirtyStateAttack3.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;

// Uncomment this line to use console.log
// import "hardhat/console.sol";
import "./IFunToken.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract TestDirtyStateAttack3 {
address erc20;
uint counter = 0;

constructor(address erc20_) payable {
erc20 = erc20_;
}

function attack(
address payable sendRecipient,
string memory bech32Recipient
) external {
counter++;
try
TestDirtyStateAttack3(payable(address(this))).transferFunds(
sendRecipient,
bech32Recipient
)
{} catch
{
counter++;
}
}

function transferFunds(
address payable sendRecipient,
string memory bech32Recipient
) external {
require(sendRecipient.send(10 ether), "ETH transfer failed"); // 10 NIBI

(bool success, ) = FUNTOKEN_PRECOMPILE_ADDRESS.call(
abi.encodeWithSignature(
"sendToBank(address,uint256,string)",
erc20,
uint256(10e6), // 10 WNIBI
bech32Recipient
)
);

require(success, string.concat("Failed to call bankSend"));

revert();
}
}
12 changes: 10 additions & 2 deletions x/evm/embeds/embeds.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ var (
testDirtyStateAttack1 []byte
//go:embed artifacts/contracts/TestDirtyStateAttack2.sol/TestDirtyStateAttack2.json
testDirtyStateAttack2 []byte
//go:embed artifacts/contracts/TestDirtyStateAttack3.sol/TestDirtyStateAttack3.json
testDirtyStateAttack3 []byte
)

var (
Expand Down Expand Up @@ -158,16 +160,21 @@ var (
Name: "TestPrecompileSendToBankThenERC20Transfer.sol",
EmbedJSON: testPrecompileSendToBankThenERC20Transfer,
}
// SmartContract_TestDirtyStateAttack1 is a test contract that sends to bank then calls ERC20 transfer
// SmartContract_TestDirtyStateAttack1 is a test contract that composes manual send and funtoken sendToBank
SmartContract_TestDirtyStateAttack1 = CompiledEvmContract{
Name: "TestDirtyStateAttack1.sol",
EmbedJSON: testDirtyStateAttack1,
}
// SmartContract_TestDirtyStateAttack2 is a test contract that sends to bank then calls ERC20 transfer
// SmartContract_TestDirtyStateAttack2 is a test contract that composes erc20 transfer and funtoken sendToBank
SmartContract_TestDirtyStateAttack2 = CompiledEvmContract{
Name: "TestDirtyStateAttack2.sol",
EmbedJSON: testDirtyStateAttack2,
}
// SmartContract_TestDirtyStateAttack3 is a test contract that composes manual send and funtoken sendToBank with a reversion
SmartContract_TestDirtyStateAttack3 = CompiledEvmContract{
Name: "TestDirtyStateAttack3.sol",
EmbedJSON: testDirtyStateAttack3,
}
)

func init() {
Expand All @@ -189,6 +196,7 @@ func init() {
SmartContract_TestPrecompileSendToBankThenERC20Transfer.MustLoad()
SmartContract_TestDirtyStateAttack1.MustLoad()
SmartContract_TestDirtyStateAttack2.MustLoad()
SmartContract_TestDirtyStateAttack3.MustLoad()
}

type CompiledEvmContract struct {
Expand Down
100 changes: 100 additions & 0 deletions x/evm/keeper/funtoken_from_coin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -958,6 +958,106 @@ func (s *FunTokenFromCoinSuite) TestDirtyStateAttack2() {
})
}

// TestDirtyStateAttack3
// 1. Creates a funtoken from coin.
// 2. Calls the test contract
// a. manual send 10 NIBI to Alice
// b. FunToken.sendToBank 10 WNIBI to Alice
// c. reverts
//
// INITIAL STATE:
// - Test contract funds: 10 WNIBI, 10 NIBI
// CONTRACT CALL:
// - Sends 10 NIBI to Alice manually
// - Sends 10 WNIBI to Alice via FunToken.sendToBank
// - reverts
// EXPECTED:
// - Test contract funds: 10 WNIBI, 10 NIBI
// - Alice: 0 WNIBI, 0 NIBI
// - Module account: 10 NIBI escrowed
func (s *FunTokenFromCoinSuite) TestDirtyStateAttack3() {
deps := evmtest.NewTestDeps()

// Initial setup
funToken := s.fundAndCreateFunToken(deps, 10e6)

s.T().Log("Deploy Test Contract")
deployResp, err := evmtest.DeployContract(
&deps,
embeds.SmartContract_TestDirtyStateAttack3,
funToken.Erc20Addr.Address,
)
s.Require().NoError(err)
testContractAddr := deployResp.ContractAddr

s.Run("Convert bank coin to erc-20: give test contract 10 WNIBI (erc20)", func() {
_, err = deps.EvmKeeper.ConvertCoinToEvm(
sdk.WrapSDKContext(deps.Ctx),
&evm.MsgConvertCoinToEvm{
Sender: deps.Sender.NibiruAddr.String(),
BankCoin: sdk.NewCoin(evm.EVMBankDenom, sdk.NewInt(10e6)),
ToEthAddr: eth.EIP55Addr{Address: testContractAddr},
},
)
s.Require().NoError(err)
})

s.Run("Send 10 NIBI to test contract manually", func() {
s.Require().NoError(testapp.FundAccount(
deps.App.BankKeeper,
deps.Ctx,
eth.EthAddrToNibiruAddr(testContractAddr),
sdk.NewCoins(sdk.NewCoin(evm.EVMBankDenom, sdk.NewInt(10e6))),
))
})

alice := evmtest.NewEthPrivAcc()

s.Run("call test contract", func() {
contractInput, err := embeds.SmartContract_TestDirtyStateAttack3.ABI.Pack(
"attack",
alice.EthAddr,
alice.NibiruAddr.String(),
)
s.Require().NoError(err)
evmObj, _ := deps.NewEVM()
_, err = deps.EvmKeeper.CallContractWithInput(
deps.Ctx,
evmObj,
deps.Sender.EthAddr,
&testContractAddr,
true,
contractInput,
evmtest.FunTokenGasLimitSendToEvm,
)
s.Require().NoError(err)

evmtest.FunTokenBalanceAssert{
FunToken: funToken,
Account: alice.EthAddr,
BalanceBank: big.NewInt(0),
BalanceERC20: big.NewInt(0),
Description: "Alice has 0 NIBI / 0 WNIBI",
}.Assert(s.T(), deps, evmObj)

evmtest.FunTokenBalanceAssert{
FunToken: funToken,
Account: testContractAddr,
BalanceBank: big.NewInt(10e6),
BalanceERC20: big.NewInt(10e6),
Description: "Test contract has 10 WNIBI / 10 NIBI",
}.Assert(s.T(), deps, evmObj)

evmtest.FunTokenBalanceAssert{
FunToken: funToken,
Account: evm.EVM_MODULE_ADDRESS,
BalanceBank: big.NewInt(10e6),
BalanceERC20: big.NewInt(0),
Description: "Module account has 10 NIBI escrowed",
}.Assert(s.T(), deps, evmObj)
})
}

// fundAndCreateFunToken creates initial setup for tests
func (s *FunTokenFromCoinSuite) fundAndCreateFunToken(deps evmtest.TestDeps, unibiAmount int64) evm.FunToken {
bankDenom := evm.EVMBankDenom
Expand Down

0 comments on commit 19db354

Please sign in to comment.