Spectral V2 allows people to create on-chain AI agents. Each agent owns a wallet that allows on-chain actions. There are three main contracts:
- AutonmousAgentDeployer.sol: handles swaps between SPEC and Agent tokens.
- AgentToken.sol: Goverance token with a taxing functionality. This tax is important for later.
- AgentBalances.sol: Manages and distributes tokens that came from taxes.
When transferFrom() is used on the token, a tax is applied to the funds being moved in AgentToken. Whenever this occurs, the AgentBalances contract is given an infinite approval to spend funds on behalf of the caller contract. Infinite approvals are prone to abuse, but they typically involve simply stealing funds.
The swapExactTokensForSPEC() function on the AutonomousAgentDeployer contract calls transferFrom(). If an attacker calls this function it gives the AgentBalances an infinite approval on this contract.
The attacker called a public deposit() function that allowed for the specifying of the from, tokenAddress and amount values on the AgentBalances contract. They don't have the ability to steal the tokens though - only transfer them somewhere else by mode of approvals. Why is this useful though?
The AutonomousAgentDeployer contract balances were used as part of the constant product market maker algorithm between AgentTokens and SPEC. Hence, if tokens were removed from the contract to somewhere else it would then change the price of the swap drastically!
So, the attacker triggered the infinite approval and exploited the approval to manipulate the price of the SPEC token. Since there is almost not AgentToken left only a small amount of AgentToken needs to be used in order to take all of the SPEC tokens. This exploit stole about 250K worth of tokens.
Overall, it is an interesting exploit! Sometimes, you find yourself with a primitive, like moving tokens from one account to another, but it isn't immediately useful. From there, you must find an exploitation route to profit from it. This feels like a good example of that.