-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcreate_asset.rs
161 lines (138 loc) · 4.91 KB
/
create_asset.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
use crate::{
utils::{
create_asset, get_and_validate_epoch, write_rawimg_and_traits,
}, Auction, EpochError, Points, Reputation, AUCTION_SEED, AUTHORITY_SEED, COLLECTION_SEED, NFT_MINT_SEED, REPUTATION_SEED
};
use anchor_lang::{prelude::*, system_program::{transfer, Transfer}};
#[derive(Accounts)]
#[instruction(input_epoch: u64)]
pub struct CreateAsset<'info> {
/// CHECK: New NFT Mint (will be init by OSS Program via CPI - address is derived based on epoch #)
#[account(
mut,
seeds = [NFT_MINT_SEED.as_bytes(), &input_epoch.to_le_bytes()],
bump,
)]
pub asset: UncheckedAccount<'info>,
#[account(mut)]
pub payer: Signer<'info>,
/// CHECK: Group Asset
#[account(
mut,
seeds = [COLLECTION_SEED.as_bytes()],
bump,
)]
pub group: UncheckedAccount<'info>,
/// CHECK: Program Authority: The account that will be used to sign transactions
#[account(
mut,
seeds = [AUTHORITY_SEED.as_bytes()],
bump,
)]
pub authority: UncheckedAccount<'info>,
pub system_program: Program<'info, System>,
/// CHECK: use address constraint
#[account(
address = nifty_asset::ID @ EpochError::InvalidOssProgram
)]
pub oss_program: UncheckedAccount<'info>,
#[account(
init,
seeds = [AUCTION_SEED.as_bytes(), &input_epoch.to_le_bytes()],
bump,
payer = payer,
space = Auction::get_size()
)]
pub auction: Account<'info, Auction>,
#[account(
init_if_needed,
seeds = [REPUTATION_SEED.as_bytes(), payer.key().as_ref()],
bump,
payer = payer,
space = Reputation::get_size(),
)]
pub reputation: Account<'info, Reputation>,
}
impl<'info> CreateAsset<'info> {
pub fn handler(
&mut self,
authority_bump: u8,
asset_bump: u8,
reputation_bump: u8,
auction_bump: u8,
current_epoch: u64,
) -> Result<()> {
let epoch = get_and_validate_epoch(current_epoch)?;
let account_infos = vec![
self.asset.to_account_info(),
self.payer.to_account_info(),
self.group.to_account_info(),
self.authority.to_account_info(),
self.oss_program.to_account_info(),
self.system_program.to_account_info(),
];
let asset_seeds = &[
NFT_MINT_SEED.as_bytes(),
&epoch.to_le_bytes(),
&[asset_bump],
];
let asset_signer_seeds: &[&[&[u8]]; 1] = &[&asset_seeds[..]];
let authority_seeds = &[AUTHORITY_SEED.as_bytes(), &[authority_bump]];
let combined_signer_seeds = &[&asset_seeds[..], &authority_seeds[..]];
write_rawimg_and_traits(
self.asset.to_account_info(),
self.payer.to_account_info(),
self.system_program.to_account_info(),
self.oss_program.to_account_info(),
&account_infos,
asset_signer_seeds,
epoch
)?;
create_asset(
self.asset.key(),
self.payer.key(),
self.authority.key(),
self.authority.key(),
self.group.key(),
&account_infos,
combined_signer_seeds,
epoch
)?;
let payer = self.payer.key();
let asset = self.asset.to_account_info();
let auction: &mut Account<'_, Auction> = &mut self.auction;
let reputation: &mut Account<'_, Reputation> = &mut self.reputation;
auction.create(
current_epoch,
asset.key(),
payer,
auction_bump,
);
reputation.init_if_needed(payer, reputation_bump);
reputation.increment_with_validation(Points::INITIATE, payer.key())?;
//TODO Replace anchor init with my own in lieu of refund.
//maybe track the amount in the auction to prevent some weird abuse where somebody sends lamports to the asset or auction pda
self.refund_rent(authority_bump)?;
Ok(())
}
fn refund_rent(&self, authority_bump: u8) -> Result<()> {
let asset_lamports = self.asset.lamports();
let auction_lamports = self.auction.to_account_info().lamports();
// Use saturating add to prevent any weird scenario where somebody is sending lamports to these accounts
let refund_amount: u64 = asset_lamports.saturating_add(auction_lamports).min(300000);
let bump = &[authority_bump];
let seeds: &[&[u8]] = &[AUTHORITY_SEED.as_ref(), bump];
let signer_seeds = &[&seeds[..]];
transfer(
CpiContext::new(
self.system_program.to_account_info(),
Transfer {
from: self.authority.to_account_info(),
to: self.payer.to_account_info(),
},
).with_signer(signer_seeds),
refund_amount,
)?;
Ok(())
}
}