Merge pull request #11392 from ethereum/evmc-transfer

EVMHost: Fix selfdestruct with non-zero value at beneficiary and value-transfers with insufficient funds
This commit is contained in:
Harikrishnan Mulackal 2021-05-17 12:27:41 +02:00 committed by GitHub
commit 85552b58d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 19 additions and 4 deletions

View File

@ -168,12 +168,19 @@ void EVMHost::reset()
} }
} }
void EVMHost::transfer(evmc::MockedAccount& _sender, evmc::MockedAccount& _recipient, u256 const& _value) noexcept
{
assertThrow(u256(convertFromEVMC(_sender.balance)) >= _value, Exception, "Insufficient balance for transfer");
_sender.balance = convertToEVMC(u256(convertFromEVMC(_sender.balance)) - _value);
_recipient.balance = convertToEVMC(u256(convertFromEVMC(_recipient.balance)) + _value);
}
void EVMHost::selfdestruct(const evmc::address& _addr, const evmc::address& _beneficiary) noexcept void EVMHost::selfdestruct(const evmc::address& _addr, const evmc::address& _beneficiary) noexcept
{ {
// TODO actual selfdestruct is even more complicated. // TODO actual selfdestruct is even more complicated.
evmc::uint256be balance = accounts[_addr].balance;
transfer(accounts[_addr], accounts[_beneficiary], convertFromEVMC(accounts[_addr].balance));
accounts.erase(_addr); accounts.erase(_addr);
accounts[_beneficiary].balance = balance;
// Record self destructs // Record self destructs
recorded_selfdestructs.push_back({_addr, _beneficiary}); recorded_selfdestructs.push_back({_addr, _beneficiary});
} }
@ -271,8 +278,14 @@ evmc::result EVMHost::call(evmc_message const& _message) noexcept
if (value != 0 && message.kind != EVMC_DELEGATECALL && message.kind != EVMC_CALLCODE) if (value != 0 && message.kind != EVMC_DELEGATECALL && message.kind != EVMC_CALLCODE)
{ {
sender.balance = convertToEVMC(u256(convertFromEVMC(sender.balance)) - value); if (value > convertFromEVMC(sender.balance))
destination.balance = convertToEVMC(u256(convertFromEVMC(destination.balance)) + value); {
evmc::result result({});
result.status_code = EVMC_INSUFFICIENT_BALANCE;
accounts = stateBackup;
return result;
}
transfer(sender, destination, value);
} }
// Populate the access access list. // Populate the access access list.

View File

@ -91,6 +91,8 @@ public:
private: private:
evmc::address m_currentAddress = {}; evmc::address m_currentAddress = {};
void transfer(evmc::MockedAccount& _sender, evmc::MockedAccount& _recipient, u256 const& _value) noexcept;
/// Records calls made via @param _message. /// Records calls made via @param _message.
void recordCalls(evmc_message const& _message) noexcept; void recordCalls(evmc_message const& _message) noexcept;