IERC20.transfer
changes it
declared only
—boolsrc/Strategy.sol:52 argument(s)
to | address |
amount | uint256 |
These are edges whose target could not be determined from source. They are not guessed and not omitted — they are the places to read by hand.
| Entry | Kind | Source line | File |
|---|---|---|---|
Vault.execute |
call | (bool ok, bytes memory out) = target.delegatecall(data); |
src/Vault.sol |
Entries that change state and need at most one principal’s consent.
anyone means no access check at all — the most open case there is, so those sort first.
| Alone | Entry | Effect | Moves | Holes | Where |
|---|---|---|---|---|---|
| anyone | Vault.deposit |
changes it | 0 | 0 | src/Vault.sol:22 |
| anyone | Vault.withdraw |
changes it | 0 | 0 | src/Vault.sol:28 |
| anyone | Vault.takeFee |
changes it | 0 | 0 | src/Vault.sol:41 |
| anyone | IERC20.transfer |
changes it | 0 | 0 | src/Strategy.sol:5 |
| anyone | IERC20.transferFrom |
changes it | 0 | 0 | src/Strategy.sol:6 |
| anyone | IRouter.swap |
changes it | 0 | 0 | src/Strategy.sol:11 |
| anyone | IStrategy.invest |
changes it | 0 | 0 | src/Strategy.sol:15 |
| anyone | IStrategy.withdraw |
changes it | 0 | 0 | src/Strategy.sol:16 |
| anyone | IStrategy.harvest |
changes it | 0 | 0 | src/Strategy.sol:17 |
| anyone | Strategy.constructor |
changes it | 0 | 0 | src/Strategy.sol:26 |
| anyone | Vault.constructor |
changes it | 0 | 0 | src/Vault.sol:20 |
onlyOwner |
Vault.execute |
changes it | 0 | 1 | src/Vault.sol:46 |
keepers[msg.sender] |
Vault.harvest |
changes it | 0 | 0 | src/Vault.sol:34 |
vault |
Strategy.harvest |
changes it | 0 | 0 | src/Strategy.sol:37 |
vault |
Strategy.withdraw |
changes it | 0 | 0 | src/Strategy.sol:32 |
vault |
Strategy.emergencyExit |
changes it | 0 | 0 | src/Strategy.sol:44 |
vault |
Strategy.invest |
changes it | 0 | 0 | src/Strategy.sol:30 |
onlyOwner |
Owned.transferOwnership |
changes it | 0 | 0 | src/Vault.sol:10 |
onlyOwner |
Vault.setStrategy |
changes it | 0 | 0 | src/Vault.sol:43 |
onlyOwner |
Vault.setKeeper |
changes it | 0 | 0 | src/Vault.sol:44 |
| From | To | Via | |
|---|---|---|---|
Strategy |
call | IERC20 |
withdraw, harvest, harvest, emergencyExit |
Strategy |
call | IRouter |
harvest |
Vault |
call | IERC20 |
deposit, deposit, deposit, withdraw, harvest, harvest, harvest, takeFee |
Vault |
call | IStrategy |
deposit, withdraw, harvest, harvest |
Unresolved edges are deliberately absent here — they are in Holes above. A graph that quietly drew a guessed target would be worse than one with a gap in it.
—src/Strategy.sol:4IERC20.transfer
changes it
declared only
—boolsrc/Strategy.sol:5to | address |
amount | uint256 |
IERC20.transferFrom
changes it
declared only
—boolsrc/Strategy.sol:6from | address |
to | address |
amount | uint256 |
IERC20.balanceOf
repeatable
declared only
—uint256src/Strategy.sol:7who | address |
—src/Strategy.sol:10IRouter.swap
changes it
declared only
—uint256src/Strategy.sol:11tokenIn | address |
tokenOut | address |
amountIn | uint256 |
—src/Strategy.sol:14IStrategy.invest
changes it
declared only
—src/Strategy.sol:15amount | uint256 |
IStrategy.withdraw
changes it
declared only
—src/Strategy.sol:16amount | uint256 |
IStrategy.harvest
changes it
declared only
—uint256src/Strategy.sol:17—src/Strategy.sol:20Strategy.constructor
changes it
runs once at deployment
—src/Strategy.sol:26_vault | address |
_asset | IERC20 |
_reward | IERC20 |
_router | IRouter |
constructor(address _vault, IERC20 _asset, IERC20 _reward, IRouter _router) {
vault = _vault; asset = _asset; reward = _reward; router = _router;
}
Shown with comments intact. Comments are stripped before parsing and were never used to produce anything above.
Strategy.invest
changes it
one principal
vaultsrc/Strategy.sol:30 | uint256 |
_onlyVault() → require(msg.sender == vault, "not vault"); function invest(uint256) external { _onlyVault(); }
Shown with comments intact. Comments are stripped before parsing and were never used to produce anything above.
Strategy.withdraw
changes it
one principal
vaultsrc/Strategy.sol:32amount | uint256 |
_onlyVault() → require(msg.sender == vault, "not vault");| call | IERC20 |
asset.transfer(vault, amount); |
function withdraw(uint256 amount) external {
_onlyVault();
asset.transfer(vault, amount);
}
Shown with comments intact. Comments are stripped before parsing and were never used to produce anything above.
Strategy.harvest
changes it
one principal
vaultuint256src/Strategy.sol:37_onlyVault() → require(msg.sender == vault, "not vault");| call | IERC20 |
uint256 earned = reward.balanceOf(address(this)); |
| call | IRouter |
gained = router.swap(address(reward), address(asset), earned); |
| call | IERC20 |
asset.transfer(vault, gained); |
function harvest() external returns (uint256 gained) {
_onlyVault();
uint256 earned = reward.balanceOf(address(this));
gained = router.swap(address(reward), address(asset), earned);
asset.transfer(vault, gained);
}
Shown with comments intact. Comments are stripped before parsing and were never used to produce anything above.
Strategy.emergencyExit
changes it
one principal
vaultsrc/Strategy.sol:44if (msg.sender != vault) revert();| call | IERC20 |
asset.transfer(vault, asset.balanceOf(address(this))); |
function emergencyExit() external {
if (msg.sender != vault) revert();
asset.transfer(vault, asset.balanceOf(address(this)));
}
Shown with comments intact. Comments are stripped before parsing and were never used to produce anything above.
—src/Vault.sol:7Owned.transferOwnership
changes it
one principal
onlyOwnersrc/Vault.sol:10to | address |
function transferOwnership(address to) external onlyOwner { owner = to; }
Shown with comments intact. Comments are stripped before parsing and were never used to produce anything above.
—src/Vault.sol:13Vault.constructor
changes it
runs once at deployment
—src/Vault.sol:20_asset | IERC20 |
constructor(IERC20 _asset) { asset = _asset; owner = msg.sender; }
Shown with comments intact. Comments are stripped before parsing and were never used to produce anything above.
Vault.deposit
changes it
—src/Vault.sol:22amount | uint256 |
| call | IERC20 |
asset.transferFrom(msg.sender, address(this), amount); |
| call | IERC20 via _invest |
uint256 idle = asset.balanceOf(address(this)); |
| call | IERC20 via _invest |
asset.transfer(address(strategy), idle); |
| call | IStrategy via _invest |
strategy.invest(idle); |
function deposit(uint256 amount) external {
asset.transferFrom(msg.sender, address(this), amount);
shares[msg.sender] += amount;
_invest();
}
Shown with comments intact. Comments are stripped before parsing and were never used to produce anything above.
Vault.withdraw
changes it
—src/Vault.sol:28amount | uint256 |
function withdraw(uint256 amount) external {
shares[msg.sender] -= amount;
strategy.withdraw(amount);
asset.transfer(msg.sender, amount);
}
Shown with comments intact. Comments are stripped before parsing and were never used to produce anything above.
Vault.harvest
changes it
one principal
keepers[msg.sender]src/Vault.sol:34_onlyKeeper() → require(keepers[msg.sender], "not keeper");| call | IStrategy |
uint256 profit = strategy.harvest(); |
| call | IERC20 via _takeFee |
asset.transfer(owner, amount * feeBps / 10_000); |
| call | IERC20 via _invest |
uint256 idle = asset.balanceOf(address(this)); |
| call | IERC20 via _invest |
asset.transfer(address(strategy), idle); |
| call | IStrategy via _invest |
strategy.invest(idle); |
function harvest() external {
_onlyKeeper();
uint256 profit = strategy.harvest();
_takeFee(profit);
_invest();
}
Shown with comments intact. Comments are stripped before parsing and were never used to produce anything above.
Vault.takeFee
changes it
—src/Vault.sol:41amount | uint256 |
| call | IERC20 via _takeFee |
asset.transfer(owner, amount * feeBps / 10_000); |
function takeFee(uint256 amount) external { _takeFee(amount); }
Shown with comments intact. Comments are stripped before parsing and were never used to produce anything above.
Vault.setStrategy
changes it
one principal
onlyOwnersrc/Vault.sol:43next | IStrategy |
function setStrategy(IStrategy next) external onlyOwner { strategy = next; }
Shown with comments intact. Comments are stripped before parsing and were never used to produce anything above.
Vault.setKeeper
changes it
one principal
onlyOwnersrc/Vault.sol:44keeper | address |
allowed | bool |
function setKeeper(address keeper, bool allowed) external onlyOwner { keepers[keeper] = allowed; }
Shown with comments intact. Comments are stripped before parsing and were never used to produce anything above.
Vault.execute
changes it
one principal
onlyOwnerbytessrc/Vault.sol:46target | address |
data | bytes |
require(ok, "call failed");| call | could not determine | (bool ok, bytes memory out) = target.delegatecall(data); |
function execute(address target, bytes calldata data) external onlyOwner returns (bytes memory) {
(bool ok, bytes memory out) = target.delegatecall(data);
require(ok, "call failed");
return out;
}
Shown with comments intact. Comments are stripped before parsing and were never used to produce anything above.