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;
}