Skip to content

Commit 6981b21

Browse files
authored
Add Arb CPI example contract
1 parent afe1413 commit 6981b21

File tree

1 file changed

+31
-2
lines changed
  • not-so-smart-contracts/solana/arbitrary_cpi

1 file changed

+31
-2
lines changed

not-so-smart-contracts/solana/arbitrary_cpi/README.md

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,36 @@ Solana allows programs to call one another through cross-program invocation (CPI
44
View ToB's lint implementation for the arbitrary CPI issue [here](https://github.com/crytic/solana-lints/tree/master/lints/arbitrary_cpi).
55

66
## Exploit Scenario
7-
7+
Consider the following `withdraw` function. Tokens are able to be withdrawn from the pool to a user account. The program invoked here is user-controlled and there's no check that program passed in is the intended `token_program`. This allows a malicious user to pass in their own program with functionality to their discretion - such as draining the pool of the inputted `amount` tokens.
88
### Example Contract
9-
9+
```rust
10+
pub fn withdraw(accounts: &[AccountInfo], amount: u64) -> ProgramResult {
11+
let account_info_iter = &mut accounts.iter();
12+
let token_program = next_account_info(account_info_iter)?;
13+
let pool = next_account_info(account_info_iter)?;
14+
let pool_auth = next_account_info(account_info_iter)?;
15+
let destination = next_account_info(account_info_iter)?;
16+
invoke(
17+
&spl_token::instruction::transfer(
18+
&token_program.key,
19+
&pool.key,
20+
&destination.key,
21+
&pool_auth.key,
22+
&[],
23+
amount,
24+
)?,
25+
&[
26+
&pool.clone(),
27+
&destination.clone(),
28+
&pool_auth.clone(),
29+
],
30+
)
31+
}
32+
```
33+
*Inspired by [Sealevel](https://github.com/coral-xyz/sealevel-attacks/)*
1034
## Mitigation
35+
```rust
36+
if INPUTTED_PROGRAM.key != &INTENDED_PROGRAM::id() {
37+
return Err(ProgramError::InvalidProgramId);
38+
}
39+
```

0 commit comments

Comments
 (0)