Summary
In BuyerAgentFactory
, the deploy function passes msg.sender
instead of the factory's address as the operator parameter to the BuyerAgent
constructor.
This breaks the intended access control model as the wrong address gets operator privileges.
Vulnerability Details
The factory incorrectly passes the caller's address as operator:
contract BuyerAgentFactory {
function deploy(
string memory _name,
string memory _description,
uint96 _royaltyFee,
uint256 _amountPerRound,
address _owner
) external returns (BuyerAgent) {
return new BuyerAgent(
_name,
_description,
_royaltyFee,
_amountPerRound,
msg.sender,
_owner
);
}
}
This impacts the BuyerAgent's authorization checks:
contract BuyerAgent is Ownable {
modifier onlyAuthorized() {
if (!swan.isOperator(msg.sender) && msg.sender != owner()) {
revert Unauthorized(msg.sender);
}
_;
}
constructor(
string memory _name,
string memory _description,
uint96 _royaltyFee,
uint256 _amountPerRound,
address _operator,
address _owner
) Ownable(_owner) {
swan = Swan(_operator);
}
}
Attack Scenario:
BuyerAgent agent = factory.deploy(
"Attack",
"Description",
royaltyFee,
amount,
owner
);
Impact
Unauthorized addresses get operator privileges
Broken authorization model
Potential for malicious actions like Unauthorized oracle requests, purchases and withdrawals
Tools Used
Manual Review
Recommendations
Pass factory address as operator:
contract BuyerAgentFactory {
function deploy(
string memory _name,
string memory _description,
uint96 _royaltyFee,
uint256 _amountPerRound,
address _owner
) external returns (BuyerAgent) {
return new BuyerAgent(
_name,
_description,
_royaltyFee,
_amountPerRound,
address(this),
_owner
);
}
}