lang: fix missing ATA owner check (#1240)

This commit is contained in:
Paul 2022-01-05 17:09:57 +01:00 committed by GitHub
parent 35c8200010
commit e026e9e874
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 110 additions and 54 deletions

View File

@ -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))

View File

@ -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());

View File

@ -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
);
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,
},
});
const client = new Token(
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,
mint.publicKey,
TOKEN_PROGRAM_ID,
program.provider.wallet.payer
program.provider.wallet.payer,
program.provider.wallet.publicKey,
program.provider.wallet.publicKey,
9,
TOKEN_PROGRAM_ID
);
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 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));
});
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("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;
}
);
});
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 () => {