Skip to content

Commit

Permalink
lang: fix missing ATA owner check (#1240)
Browse files Browse the repository at this point in the history
  • Loading branch information
paul-schaaf committed Jan 5, 2022
1 parent 35c8200 commit e026e9e
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 53 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -13,6 +13,7 @@ incremented for features.

### Fixes

* lang: Add missing owner check when `associated_token::authority` is used ([#1240](https://github.com/project-serum/anchor/pull/1240)).
* ts: Add type declarations for conditional `workspace` and `Wallet` exports ([#1137](https://github.com/project-serum/anchor/pull/1137)).
* ts: Change commitment message `recent` to `processed` and `max` to `finalized` ([#1128](https://github.com/project-serum/anchor/pull/1128))
* ts: fix `translateAddress` which currently leads to failing browser code. Now uses `PublicKey` constructor instead of prototype chain constructor name checking which doesn't work in the presence of code minifying/mangling([#1138](https://github.com/project-serum/anchor/pull/1138))
Expand Down
3 changes: 3 additions & 0 deletions lang/syn/src/codegen/accounts/constraints.rs
Expand Up @@ -395,6 +395,9 @@ fn generate_constraint_associated_token(
let wallet_address = &c.wallet;
let spl_token_mint_address = &c.mint;
quote! {
if #name.owner != #wallet_address.key() {
return Err(anchor_lang::__private::ErrorCode::ConstraintTokenOwner.into());
}
let __associated_token_address = anchor_spl::associated_token::get_associated_token_address(&#wallet_address.key(), &#spl_token_mint_address.key());
if #name.key() != __associated_token_address {
return Err(anchor_lang::__private::ErrorCode::ConstraintAssociated.into());
Expand Down
158 changes: 105 additions & 53 deletions tests/misc/tests/misc.js
Expand Up @@ -614,65 +614,117 @@ describe("misc", () => {
assert.equal(account2.idata, 3);
});

let associatedToken = null;

it("Can create an associated token account", async () => {
associatedToken = await Token.getAssociatedTokenAddress(
ASSOCIATED_TOKEN_PROGRAM_ID,
TOKEN_PROGRAM_ID,
mint.publicKey,
program.provider.wallet.publicKey
describe("associated_token constraints", () => {
let associatedToken = null;
// apparently cannot await here so doing it in the 'it' statements
let client = Token.createMint(
program.provider.connection,
program.provider.wallet.payer,
program.provider.wallet.publicKey,
program.provider.wallet.publicKey,
9,
TOKEN_PROGRAM_ID
);

await program.rpc.testInitAssociatedToken({
accounts: {
token: associatedToken,
mint: mint.publicKey,
payer: program.provider.wallet.publicKey,
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
systemProgram: anchor.web3.SystemProgram.programId,
tokenProgram: TOKEN_PROGRAM_ID,
associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID,
},
it("Can create an associated token account", async () => {
const localClient = await client;
associatedToken = await Token.getAssociatedTokenAddress(
ASSOCIATED_TOKEN_PROGRAM_ID,
TOKEN_PROGRAM_ID,
localClient.publicKey,
program.provider.wallet.publicKey
);

await program.rpc.testInitAssociatedToken({
accounts: {
token: associatedToken,
mint: localClient.publicKey,
payer: program.provider.wallet.publicKey,
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
systemProgram: anchor.web3.SystemProgram.programId,
tokenProgram: TOKEN_PROGRAM_ID,
associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID,
},
});

const account = await localClient.getAccountInfo(associatedToken);
assert.ok(account.state === 1);
assert.ok(account.amount.toNumber() === 0);
assert.ok(account.isInitialized);
assert.ok(account.owner.equals(program.provider.wallet.publicKey));
assert.ok(account.mint.equals(localClient.publicKey));
});
const client = new Token(
program.provider.connection,
mint.publicKey,
TOKEN_PROGRAM_ID,
program.provider.wallet.payer
);
const account = await client.getAccountInfo(associatedToken);
assert.ok(account.state === 1);
assert.ok(account.amount.toNumber() === 0);
assert.ok(account.isInitialized);
assert.ok(account.owner.equals(program.provider.wallet.publicKey));
assert.ok(account.mint.equals(mint.publicKey));
});

it("Can validate associated_token constraints", async () => {
await program.rpc.testValidateAssociatedToken({
accounts: {
token: associatedToken,
mint: mint.publicKey,
wallet: program.provider.wallet.publicKey,
},
it("Can validate associated_token constraints", async () => {
const localClient = await client;
await program.rpc.testValidateAssociatedToken({
accounts: {
token: associatedToken,
mint: localClient.publicKey,
wallet: program.provider.wallet.publicKey,
},
});

let otherMint = await Token.createMint(
program.provider.connection,
program.provider.wallet.payer,
program.provider.wallet.publicKey,
program.provider.wallet.publicKey,
9,
TOKEN_PROGRAM_ID
);

await assert.rejects(
async () => {
await program.rpc.testValidateAssociatedToken({
accounts: {
token: associatedToken,
mint: otherMint.publicKey,
wallet: program.provider.wallet.publicKey,
},
});
},
(err) => {
assert.equal(err.code, 2009);
return true;
}
);
});

await assert.rejects(
async () => {
await program.rpc.testValidateAssociatedToken({
accounts: {
token: associatedToken,
mint: mint.publicKey,
wallet: anchor.web3.Keypair.generate().publicKey,
},
});
},
(err) => {
assert.equal(err.code, 2009);
return true;
}
);
it("associated_token constraints check do not allow authority change", async () => {
const localClient = await client;
await program.rpc.testValidateAssociatedToken({
accounts: {
token: associatedToken,
mint: localClient.publicKey,
wallet: program.provider.wallet.publicKey,
},
});

await localClient.setAuthority(
associatedToken,
anchor.web3.Keypair.generate().publicKey,
"AccountOwner",
program.provider.wallet.payer,
[]
);

await assert.rejects(
async () => {
await program.rpc.testValidateAssociatedToken({
accounts: {
token: associatedToken,
mint: localClient.publicKey,
wallet: program.provider.wallet.publicKey,
},
});
},
(err) => {
assert.equal(err.code, 2015);
return true;
}
);
});
});

it("Can fetch all accounts of a given type", async () => {
Expand Down

0 comments on commit e026e9e

Please sign in to comment.