Powerful Honeysuckle Anteater
High
TransferFrom function in the ABONDToken contract sets the updated fromState
, wrongly to the msg.sender
, instead of the from address, which gave approval to the msg.sender
.
transferFrom's purpose is to give other users approvals for transfers, so it should update the state of the from user specified.
The problem is that we are updating userStates[msg.sender]
for msg.sender instead of userStates[from]
Reference; Abond_Token.sol#L147-L170
function transferFrom(address from, address to, uint256 value) public override returns (bool) {
// check the input params are non zero
require(from != address(0) && to != address(0), "Invalid User");
// get the sender and receiver state
State memory fromState = userStates[from];
State memory toState = userStates[to];
// update receiver state
toState = Colors._credit(fromState, toState, uint128(value));
userStates[to] = toState;
// update sender state
fromState = Colors._debit(fromState, uint128(value));
//@audit-issue this is using msg.sender instead of "from" address
@>> userStates[msg.sender] = fromState;
// transfer abond
super.transferFrom(from, to, value);
return true;
}
- User A gives approval to User B to transfer ABOND tokens.
- User B transfers the token using
transferFrom
. - The state becomes corrupted as User B receives the updated state of User A.
Another possible scenario is yield duplication.
A malicious party could exploit this by using two separate addresses, one of which has a better fromState
in terms of ethBacked
, and duplicate that state to another address using transferFrom
.
The user state logic in the ABOND token is utilized in the Treasury and Borrow contracts to calculate yield. This could potentially increase or decrease rewards. A malicious party could exploit this to print free yield by duplicating a better state.
function transferFrom(address from, address to, uint256 value) public override returns (bool) {
// check the input params are non zero
require(from != address(0) && to != address(0), "Invalid User");
// get the sender and receiver state
State memory fromState = userStates[from];
State memory toState = userStates[to];
// update receiver state
toState = Colors._credit(fromState, toState, uint128(value));
userStates[to] = toState;
// update sender state
fromState = Colors._debit(fromState, uint128(value));
- userStates[msg.sender] = fromState;
+ userStates[from] = fromState;
// transfer abond
super.transferFrom(from, to, value);
return true;
}