Arbiswap Rugpull Investigation
Arbiswap ($ARBI) rug pull about $132,000 worth of losses.
SECURI LAB incidence response and red team experts have been following up on the Arbiswap ($ARBI) rug pull incident.
The event occurred around March 3, 2023 (UTC+7).
The creator of the Arbiswap Contract (contract creator 0x8a60f91178da2F9de3D7a825380B7CE03933724F) performed a rug pull (details under investigation) and transferred ~84.6 anyETH to the Multichain Router for a bridge to Ethereum, delivered to the destination. 0x8a60f91178da2F9de3D7a825380B7CE03933724F This is the same address that was on Ethereum, after which money was laundered through the Tornado Cash Router.
[Confirmation Scenario] Arbiswap rugpull with mint function
Contract Creator has used the mint function that’s our Warning Avoidance System (WAS) has detected a critical function on ArbiToken Contract on Lines: 847–850, 888–894, 959–962
https://arbiscan.io/address/0x9db8a10c7fe60d84397860b3af2e686d4f90c2b7#code
function mint(uint256 amount) public onlyOwner returns (bool) {
_mint(_msgSender(), amount);
return true;
}
function _mint(address account, uint256 amount) internal {
require(account != address(0), 'BEP20: mint to the zero address');
_totalSupply = _totalSupply.add(amount);
_balances[account] = _balances[account].add(amount);
emit Transfer(address(0), account, amount);
}
function mint(address _to, uint256 _amount) public onlyOwner {
_mint(_to, _amount);
_moveDelegates(address(0), _delegates[_to], _amount);
}
This is a scenario for minting around 1,000,000,000,000 ARBI and then dump with swap exact
and In SmartChefInitializable Our SECURI LAB Auto WAS (Warning Avoidance System) We find the existence of a function solidity-upgradable-constructor [High Severity] This may be the reason why constructor data can be changed.
(https://arbiscan.io/tx/0x6b7a0c5adf31178901123aa3cb326c76efe92fff812ef62c1b84a5cb4f41efa7).
SmartChefInitializable.sol:608
function initialize(
IERC20Metadata _stakedToken,
IERC20Metadata _rewardToken,
uint256 _rewardPerSec,
uint256 _startTime,
uint256 _bonusEndTime
) external onlyOwner {
require(!isInitialized, "Already initialized");
// Make this contract initialized
isInitialized = true;
stakedToken = _stakedToken;
rewardToken = _rewardToken;
rewardPerSec = _rewardPerSec;
startTime = _startTime;
bonusEndTime = _bonusEndTime;
uint256 decimalsRewardToken = uint256(rewardToken.decimals());
require(decimalsRewardToken < 30, "Must be less than 30");
PRECISION_FACTOR = uint256(10**(uint256(30) - decimalsRewardToken));
// Set the lastRewardTime as the startTime
lastRewardTime = startTime;
}
And we found the presence of the DelegateCall function, which may cause the function to be called somewhere non-contract SmartChefInitializable.sol:424
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
About SECURI LAB (Thailand)
As a team of highly skilled cybersecurity experts, SECURI LAB was established in 2018. Our team of security researchers has amassed over three years of expertise, and we have a strong foundation as consultants for organizations seeking to enhance their cybersecurity measures. Utilizing only the most reliable and industry-leading inspection tools, we strive to deliver the most comprehensive and effective solutions for our clients.
Follow SECURI LAB On:
Website: https://securi-lab.com/
Twitter: https://twitter.com/SECURI_LAB
Telegram: https://t.me/securi_lab
Medium: https://medium.com/@securi