Fix error codes
This commit is contained in:
parent
bc16d7d509
commit
a5945de3a7
|
@ -1,10 +1,13 @@
|
|||
use anchor_lang::prelude::*;
|
||||
|
||||
#[error_code]
|
||||
pub enum SaleError {
|
||||
pub enum ContributorError {
|
||||
#[msg("AmountTooLarge")]
|
||||
AmountTooLarge,
|
||||
|
||||
#[msg("BuyerInactive")]
|
||||
BuyerInactive,
|
||||
|
||||
#[msg("ContributionTooEarly")]
|
||||
ContributionTooEarly,
|
||||
|
||||
|
@ -56,12 +59,3 @@ pub enum SaleError {
|
|||
#[msg("TooManyAcceptedTokens")]
|
||||
TooManyAcceptedTokens,
|
||||
}
|
||||
|
||||
#[error_code]
|
||||
pub enum BuyerError {
|
||||
#[msg("BuyerInactive")]
|
||||
BuyerInactive,
|
||||
|
||||
#[msg("InvalidTokenIndex")]
|
||||
InvalidTokenIndex,
|
||||
}
|
||||
|
|
|
@ -251,13 +251,13 @@ pub mod anchor_contributor {
|
|||
|
||||
pub fn claim_refund(ctx: Context<ClaimRefund>) -> Result<()> {
|
||||
let sale = &mut ctx.accounts.sale;
|
||||
require!(sale.is_aborted(), SaleError::SaleNotAborted);
|
||||
require!(sale.is_aborted(), ContributorError::SaleNotAborted);
|
||||
|
||||
let refunds = ctx.accounts.buyer.claim_refunds(&sale.totals)?;
|
||||
let atas = &ctx.remaining_accounts;
|
||||
require!(
|
||||
atas.len() == 2 * sale.totals.len(),
|
||||
SaleError::InvalidRemainingAccounts
|
||||
ContributorError::InvalidRemainingAccounts
|
||||
);
|
||||
|
||||
let owner = &ctx.accounts.owner.key();
|
||||
|
@ -272,10 +272,13 @@ pub mod anchor_contributor {
|
|||
let mint = token::accessor::mint(&buyer_ata)?;
|
||||
require!(
|
||||
sale.get_token_index(&mint).is_ok(),
|
||||
SaleError::InvalidRemainingAccounts
|
||||
ContributorError::InvalidRemainingAccounts
|
||||
);
|
||||
let authority = token::accessor::authority(&buyer_ata)?;
|
||||
require!(authority == *owner, SaleError::InvalidRemainingAccounts);
|
||||
require!(
|
||||
authority == *owner,
|
||||
ContributorError::InvalidRemainingAccounts
|
||||
);
|
||||
}
|
||||
|
||||
let custodian_index = buyer_index + 1;
|
||||
|
@ -284,10 +287,13 @@ pub mod anchor_contributor {
|
|||
let mint = token::accessor::mint(&custodian_ata)?;
|
||||
require!(
|
||||
sale.get_token_index(&mint).is_ok(),
|
||||
SaleError::InvalidRemainingAccounts
|
||||
ContributorError::InvalidRemainingAccounts
|
||||
);
|
||||
let authority = token::accessor::authority(&custodian_ata)?;
|
||||
require!(authority == *custodian, SaleError::InvalidRemainingAccounts);
|
||||
require!(
|
||||
authority == *custodian,
|
||||
ContributorError::InvalidRemainingAccounts
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: transfer back to owner
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use anchor_lang::prelude::*;
|
||||
use num_derive::*;
|
||||
|
||||
use crate::{constants::ACCEPTED_TOKENS_MAX, error::BuyerError, state::sale::AssetTotal};
|
||||
use crate::{constants::ACCEPTED_TOKENS_MAX, error::ContributorError, state::sale::AssetTotal};
|
||||
|
||||
#[account]
|
||||
pub struct Buyer {
|
||||
|
@ -30,8 +30,11 @@ impl Buyer {
|
|||
}
|
||||
|
||||
pub fn contribute(&mut self, idx: usize, amount: u64) -> Result<()> {
|
||||
require!(self.is_active(), BuyerError::BuyerInactive);
|
||||
require!(idx < ACCEPTED_TOKENS_MAX, BuyerError::InvalidTokenIndex);
|
||||
require!(self.is_active(), ContributorError::BuyerInactive);
|
||||
require!(
|
||||
idx < ACCEPTED_TOKENS_MAX,
|
||||
ContributorError::InvalidTokenIndex
|
||||
);
|
||||
self.contributed[idx] += amount;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -40,7 +43,7 @@ impl Buyer {
|
|||
// total allocations and excess contributions for each
|
||||
// token index
|
||||
pub fn claim_allocations(&mut self, totals: &Vec<AssetTotal>) -> Result<Vec<BuyerTotal>> {
|
||||
require!(self.is_active(), BuyerError::BuyerInactive);
|
||||
require!(self.is_active(), ContributorError::BuyerInactive);
|
||||
|
||||
let mut buyer_totals: Vec<BuyerTotal> = Vec::with_capacity(totals.len());
|
||||
for (i, asset) in totals.iter().enumerate() {
|
||||
|
@ -64,7 +67,7 @@ impl Buyer {
|
|||
}
|
||||
|
||||
pub fn claim_refunds(&mut self, totals: &Vec<AssetTotal>) -> Result<Vec<BuyerTotal>> {
|
||||
require!(self.is_active(), BuyerError::BuyerInactive);
|
||||
require!(self.is_active(), ContributorError::BuyerInactive);
|
||||
|
||||
let mut refunds: Vec<BuyerTotal> = Vec::with_capacity(totals.len());
|
||||
for (i, asset) in totals.iter().enumerate() {
|
||||
|
|
|
@ -7,7 +7,7 @@ use std::{str::FromStr, u64};
|
|||
use crate::{
|
||||
constants::*,
|
||||
env::*,
|
||||
error::SaleError,
|
||||
error::ContributorError,
|
||||
wormhole::{get_message_data, MessageData},
|
||||
};
|
||||
|
||||
|
@ -68,7 +68,7 @@ impl AssetTotal {
|
|||
pub fn make_from_slice(bytes: &[u8]) -> Result<Self> {
|
||||
require!(
|
||||
bytes.len() == INDEX_ACCEPTED_TOKEN_END,
|
||||
SaleError::InvalidAcceptedTokenPayload
|
||||
ContributorError::InvalidAcceptedTokenPayload
|
||||
);
|
||||
Ok(AssetTotal {
|
||||
token_index: bytes[INDEX_ACCEPTED_TOKEN_INDEX],
|
||||
|
@ -99,20 +99,20 @@ impl Sale {
|
|||
}
|
||||
|
||||
pub fn parse_sale_init(&mut self, payload: &[u8]) -> Result<()> {
|
||||
require!(!self.initialized, SaleError::SaleAlreadyInitialized);
|
||||
require!(!self.initialized, ContributorError::SaleAlreadyInitialized);
|
||||
self.initialized = true;
|
||||
|
||||
// check that the payload has at least the number of bytes
|
||||
// required to define the number of accepted tokens
|
||||
require!(
|
||||
payload.len() > INDEX_SALE_INIT_ACCEPTED_TOKENS_START,
|
||||
SaleError::IncorrectVaaPayload
|
||||
ContributorError::IncorrectVaaPayload
|
||||
);
|
||||
|
||||
let num_accepted = payload[INDEX_SALE_INIT_ACCEPTED_TOKENS_START] as usize;
|
||||
require!(
|
||||
num_accepted <= ACCEPTED_TOKENS_MAX,
|
||||
SaleError::TooManyAcceptedTokens
|
||||
ContributorError::TooManyAcceptedTokens
|
||||
);
|
||||
|
||||
self.totals = Vec::with_capacity(ACCEPTED_TOKENS_MAX);
|
||||
|
@ -150,7 +150,7 @@ impl Sale {
|
|||
pub fn set_native_sale_token_decimals(&mut self, decimals: u8) -> Result<()> {
|
||||
require!(
|
||||
self.token_decimals >= decimals,
|
||||
SaleError::InvalidTokenDecimals
|
||||
ContributorError::InvalidTokenDecimals
|
||||
);
|
||||
self.native_token_decimals = decimals;
|
||||
Ok(())
|
||||
|
@ -158,7 +158,7 @@ impl Sale {
|
|||
|
||||
pub fn get_token_index(&self, mint: &Pubkey) -> Result<u8> {
|
||||
let result = self.totals.iter().find(|item| item.mint == *mint);
|
||||
require!(result != None, SaleError::InvalidTokenIndex);
|
||||
require!(result != None, ContributorError::InvalidTokenIndex);
|
||||
Ok(result.unwrap().token_index)
|
||||
}
|
||||
|
||||
|
@ -177,12 +177,12 @@ impl Sale {
|
|||
token_index: u8,
|
||||
contributed: u64,
|
||||
) -> Result<usize> {
|
||||
require!(self.is_active(block_time), SaleError::SaleEnded);
|
||||
require!(self.is_active(block_time), ContributorError::SaleEnded);
|
||||
|
||||
let block_time = block_time as u64;
|
||||
require!(
|
||||
block_time >= self.times.start,
|
||||
SaleError::ContributionTooEarly
|
||||
ContributorError::ContributionTooEarly
|
||||
);
|
||||
let idx = self.get_index(token_index)?;
|
||||
self.totals[idx].contributions += contributed;
|
||||
|
@ -191,7 +191,10 @@ impl Sale {
|
|||
}
|
||||
|
||||
pub fn serialize_contributions(&self, block_time: i64) -> Result<Vec<u8>> {
|
||||
require!(self.is_attestable(block_time), SaleError::SaleNotAttestable);
|
||||
require!(
|
||||
self.is_attestable(block_time),
|
||||
ContributorError::SaleNotAttestable
|
||||
);
|
||||
|
||||
let totals = &self.totals;
|
||||
let mut attested: Vec<u8> = Vec::with_capacity(
|
||||
|
@ -211,19 +214,19 @@ impl Sale {
|
|||
}
|
||||
|
||||
pub fn parse_sale_sealed(&mut self, payload: &[u8]) -> Result<()> {
|
||||
require!(!self.has_ended(), SaleError::SaleEnded);
|
||||
require!(!self.has_ended(), ContributorError::SaleEnded);
|
||||
// check that the payload has at least the number of bytes
|
||||
// required to define the number of allocations
|
||||
require!(
|
||||
payload.len() > INDEX_SALE_SEALED_ALLOCATIONS_START,
|
||||
SaleError::IncorrectVaaPayload
|
||||
ContributorError::IncorrectVaaPayload
|
||||
);
|
||||
|
||||
let totals = &mut self.totals;
|
||||
let num_allocations = payload[INDEX_SALE_SEALED_ALLOCATIONS_START] as usize;
|
||||
require!(
|
||||
num_allocations == totals.len(),
|
||||
SaleError::IncorrectVaaPayload
|
||||
ContributorError::IncorrectVaaPayload
|
||||
);
|
||||
|
||||
let grand_total_allocations: u64 = 0;
|
||||
|
@ -242,7 +245,7 @@ impl Sale {
|
|||
let adjusted = allocation / BigUint::from(10u128).pow(decimal_difference);
|
||||
require!(
|
||||
adjusted < BigUint::from(u64::MAX),
|
||||
SaleError::AmountTooLarge
|
||||
ContributorError::AmountTooLarge
|
||||
);
|
||||
|
||||
// is there a better way to do this part?
|
||||
|
@ -254,7 +257,7 @@ impl Sale {
|
|||
);
|
||||
require!(
|
||||
excess_contributions > BigUint::from(0 as u128),
|
||||
SaleError::AmountTooLarge
|
||||
ContributorError::AmountTooLarge
|
||||
);
|
||||
|
||||
let total = &mut totals[i];
|
||||
|
@ -273,13 +276,13 @@ impl Sale {
|
|||
}
|
||||
|
||||
pub fn parse_sale_aborted(&mut self, payload: &[u8]) -> Result<()> {
|
||||
require!(!self.has_ended(), SaleError::SaleEnded);
|
||||
require!(!self.has_ended(), ContributorError::SaleEnded);
|
||||
|
||||
// check that the payload has the correct size
|
||||
// payload type + sale id
|
||||
require!(
|
||||
payload.len() == PAYLOAD_HEADER_LEN,
|
||||
SaleError::IncorrectVaaPayload
|
||||
ContributorError::IncorrectVaaPayload
|
||||
);
|
||||
|
||||
// finally set the status to aborted
|
||||
|
@ -313,7 +316,7 @@ impl Sale {
|
|||
.totals
|
||||
.iter()
|
||||
.position(|item| item.token_index == token_index);
|
||||
require!(result != None, SaleError::InvalidTokenIndex);
|
||||
require!(result != None, ContributorError::InvalidTokenIndex);
|
||||
Ok(result.unwrap())
|
||||
}
|
||||
|
||||
|
@ -343,17 +346,20 @@ pub fn verify_conductor_vaa<'info>(
|
|||
|
||||
require!(
|
||||
vaa_account.to_account_info().owner == &Pubkey::from_str(CORE_BRIDGE_ADDRESS).unwrap(),
|
||||
SaleError::InvalidVaaAction
|
||||
ContributorError::InvalidVaaAction
|
||||
);
|
||||
require!(
|
||||
msg.emitter_chain == get_conductor_chain()?,
|
||||
SaleError::InvalidConductor
|
||||
ContributorError::InvalidConductor
|
||||
);
|
||||
require!(
|
||||
msg.emitter_address == get_conductor_address()?,
|
||||
SaleError::InvalidConductor
|
||||
ContributorError::InvalidConductor
|
||||
);
|
||||
require!(
|
||||
msg.payload[0] == payload_type,
|
||||
ContributorError::InvalidVaaAction
|
||||
);
|
||||
require!(msg.payload[0] == payload_type, SaleError::InvalidVaaAction);
|
||||
Ok(msg)
|
||||
}
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ describe("anchor-contributor", () => {
|
|||
const tokenAccount = await getOrCreateAssociatedTokenAccount(connection, buyer, mint, buyer.publicKey);
|
||||
|
||||
// now mint to buyer for testing
|
||||
let amount = new BN("20000000000");
|
||||
let amount = new BN("200000000000");
|
||||
await mintTo(
|
||||
connection,
|
||||
orchestrator,
|
||||
|
@ -193,7 +193,7 @@ describe("anchor-contributor", () => {
|
|||
let caughtError = false;
|
||||
try {
|
||||
const tx = await contributor.initSale(orchestrator, dummyConductor.initSaleVaa);
|
||||
console.log("should not happen", tx);
|
||||
throw Error(`should not happen: ${tx}`);
|
||||
} catch (e) {
|
||||
// pda init should fail
|
||||
caughtError = "programErrorStack" in e;
|
||||
|
@ -212,7 +212,7 @@ describe("anchor-contributor", () => {
|
|||
try {
|
||||
const mint = hexToPublicKey(dummyConductor.acceptedTokens[0].address);
|
||||
const tx = await contributor.contribute(buyer, saleId, mint, new BN(amount));
|
||||
console.log("should not happen", tx);
|
||||
throw Error(`should not happen: ${tx}`);
|
||||
} catch (e) {
|
||||
caughtError = verifyErrorMsg(e, "ContributionTooEarly");
|
||||
}
|
||||
|
@ -328,7 +328,7 @@ describe("anchor-contributor", () => {
|
|||
let caughtError = false;
|
||||
try {
|
||||
const tx = await contributor.attestContributions(orchestrator, saleId);
|
||||
console.log("should not happen", tx);
|
||||
throw Error(`should not happen: ${tx}`);
|
||||
} catch (e) {
|
||||
caughtError = verifyErrorMsg(e, "SaleNotAttestable");
|
||||
}
|
||||
|
@ -354,23 +354,6 @@ describe("anchor-contributor", () => {
|
|||
//expect(caughtError).to.be.false;
|
||||
});
|
||||
|
||||
// TODO
|
||||
it("Orchestrator Cannot Attest Contributions Again", async () => {
|
||||
const saleId = dummyConductor.getSaleId();
|
||||
|
||||
let caughtError = false;
|
||||
try {
|
||||
const tx = await contributor.attestContributions(orchestrator, saleId);
|
||||
console.log("should not happen", tx);
|
||||
} catch (e) {
|
||||
caughtError = verifyErrorMsg(e, "SaleNotAttestable");
|
||||
}
|
||||
|
||||
if (!caughtError) {
|
||||
throw Error("did not catch expected error");
|
||||
}
|
||||
});
|
||||
|
||||
it("User Cannot Contribute After Sale Ended", async () => {
|
||||
const saleId = dummyConductor.getSaleId();
|
||||
const amount = new BN("1000000000"); // 1,000,000,000 lamports
|
||||
|
@ -379,7 +362,7 @@ describe("anchor-contributor", () => {
|
|||
try {
|
||||
const mint = hexToPublicKey(dummyConductor.acceptedTokens[0].address);
|
||||
const tx = await contributor.contribute(buyer, saleId, mint, amount);
|
||||
console.log("should not happen", tx);
|
||||
throw Error(`should not happen: ${tx}`);
|
||||
} catch (e) {
|
||||
caughtError = verifyErrorMsg(e, "SaleEnded");
|
||||
}
|
||||
|
@ -414,7 +397,7 @@ describe("anchor-contributor", () => {
|
|||
let caughtError = false;
|
||||
try {
|
||||
const tx = await contributor.sealSale(orchestrator, saleSealedVaa);
|
||||
console.log("should not happen", tx);
|
||||
throw Error(`should not happen: ${tx}`);
|
||||
} catch (e) {
|
||||
caughtError = verifyErrorMsg(e, "SaleEnded");
|
||||
}
|
||||
|
@ -422,13 +405,6 @@ describe("anchor-contributor", () => {
|
|||
if (!caughtError) {
|
||||
throw Error("did not catch expected error");
|
||||
}
|
||||
|
||||
expect(false).to.be.true;
|
||||
});
|
||||
|
||||
// TODO
|
||||
it("User Cannot Claim Allocations with Incorrect Token Index", async () => {
|
||||
expect(false).to.be.true;
|
||||
});
|
||||
|
||||
// TODO
|
||||
|
@ -546,7 +522,7 @@ describe("anchor-contributor", () => {
|
|||
let caughtError = false;
|
||||
try {
|
||||
const tx = await contributor.abortSale(orchestrator, saleAbortedVaa);
|
||||
console.log("should not happen", tx);
|
||||
throw Error(`should not happen: ${tx}`);
|
||||
} catch (e) {
|
||||
caughtError = verifyErrorMsg(e, "SaleEnded");
|
||||
}
|
||||
|
@ -563,7 +539,9 @@ describe("anchor-contributor", () => {
|
|||
return hexToPublicKey(token.address);
|
||||
});
|
||||
|
||||
//const tx = await contributor.claimRefund(buyer, saleId, acceptedMints);
|
||||
const tx = await contributor.claimRefund(buyer, saleId, acceptedMints);
|
||||
|
||||
// get buyer state and verify inactive
|
||||
});
|
||||
|
||||
// TODO
|
||||
|
@ -575,8 +553,8 @@ describe("anchor-contributor", () => {
|
|||
|
||||
let caughtError = false;
|
||||
try {
|
||||
//const tx = await contributor.claimRefund(saleId, buyer, acceptedMints);
|
||||
//console.log("should not happen", tx);
|
||||
const tx = await contributor.claimRefund(buyer, saleId, acceptedMints);
|
||||
throw Error(`should not happen: ${tx}`);
|
||||
} catch (e) {
|
||||
caughtError = verifyErrorMsg(e, "BuyerInactive");
|
||||
}
|
||||
|
@ -595,7 +573,7 @@ function verifyErrorMsg(e: any, msg: string): boolean {
|
|||
console.error(e);
|
||||
}
|
||||
return result;
|
||||
} else if (e.error.errorMessage) {
|
||||
} else if (e.error) {
|
||||
const result = e.error.errorMessage == msg;
|
||||
if (!result) {
|
||||
console.error(e);
|
||||
|
|
Loading…
Reference in New Issue