Potential re-entrancy issues when upgrading the contracts
The protocol doesn't have any built-in re-entrancy protection mechanisms. That mainly explains by using the `wFIL` token, which is not supposed to give that opportunity. And also by carefully using `FIL` transfers.\\nHowever, there are some places in the code where things may go wrong in the future. For example, when upgrading an Agent:\\n```\\nfunction upgradeAgent(\\n address agent\\n) external returns (address newAgent) {\\n IAgent oldAgent = IAgent(agent);\\n address owner = IAuth(address(oldAgent)).owner();\\n uint256 agentId = agents[agent];\\n // only the Agent's owner can upgrade, and only a registered agent can be upgraded\\n if (owner != msg.sender || agentId == 0) revert Unauthorized();\\n // deploy a new instance of Agent with the same ID and auth\\n newAgent = GetRoute.agentDeployer(router).deploy(\\n router,\\n agentId,\\n owner,\\n IAuth(address(oldAgent)).operator()\\n );\\n // Register the new agent and unregister the old agent\\n agents[newAgent] = agentId;\\n // transfer funds from old agent to new agent and mark old agent as decommissioning\\n oldAgent.decommissionAgent(newAgent);\\n // delete the old agent from the registry\\n agents[agent] = 0;\\n}\\n```\\n\\nHere, we see the `oldAgent.decommissionAgent(newAgent);` call happens before the `oldAgent` is deleted. Inside this function, we see:\\n```\\nfunction decommissionAgent(address \\_newAgent) external {\\n // only the agent factory can decommission an agent\\n AuthController.onlyAgentFactory(router, msg.sender);\\n // if the newAgent has a mismatching ID, revert\\n if(IAgent(\\_newAgent).id() != id) revert Unauthorized();\\n // set the newAgent in storage, which marks the upgrade process as starting\\n newAgent = \\_newAgent;\\n uint256 \\_liquidAssets = liquidAssets();\\n // Withdraw all liquid funds from the Agent to the newAgent\\n \\_poolFundsInFIL(\\_liquidAssets);\\n // transfer funds to new agent\\n payable(\\_newAgent).sendValue(\\_liquidAssets);\\n}\\n```\\n\\nHere, the FIL is transferred to a new contract which is currently unimplemented and unknown. Potentially, the fallback function of this contract could trigger a re-entrancy attack. If that's the case, during the execution of this function, there will be two contracts that are active agents with the same ID, and the attacker can try to use that maliciously.
Be very cautious with further implementations of agents and pools. Also, consider using reentrancy protection in public functions.
```\\nfunction upgradeAgent(\\n address agent\\n) external returns (address newAgent) {\\n IAgent oldAgent = IAgent(agent);\\n address owner = IAuth(address(oldAgent)).owner();\\n uint256 agentId = agents[agent];\\n // only the Agent's owner can upgrade, and only a registered agent can be upgraded\\n if (owner != msg.sender || agentId == 0) revert Unauthorized();\\n // deploy a new instance of Agent with the same ID and auth\\n newAgent = GetRoute.agentDeployer(router).deploy(\\n router,\\n agentId,\\n owner,\\n IAuth(address(oldAgent)).operator()\\n );\\n // Register the new agent and unregister the old agent\\n agents[newAgent] = agentId;\\n // transfer funds from old agent to new agent and mark old agent as decommissioning\\n oldAgent.decommissionAgent(newAgent);\\n // delete the old agent from the registry\\n agents[agent] = 0;\\n}\\n```\\n