实践:利用泛型漏洞伪造投票凭证。
引言
以下是一个简单的投票系统的合约,每个地址可以领取100数量的coin然后进行投票,但是存在一些漏洞问题请尝试找出问题。
module votechain::vote {
use sui::object_table::{Self, ObjectTable};
use sui::coin::{Self,TreasuryCap};
use sui::transfer::{public_transfer, share_object, public_freeze_object};
use std::string::String;
use sui::table::{Self, Table};
public struct VOTE has drop {}
public struct Votecap has key {
id: UID,
cap: TreasuryCap<VOTE>
}
public struct Mintlist has key {
id: UID,
mintlist: Table<address, u64>
}
public struct VoteToken<phantom T> has key, store {
id: UID,
amount: u64,
}
public struct VoteStore has key {
id: UID,
proposals: ObjectTable<String, Proposal>,
}
public struct Proposal has key, store {
id: UID,
votes: u64,
}
fun init(waitness: VOTE,ctx: &mut TxContext) {
let name = std::string::utf8(b"letsctf");
let mintlist = Mintlist { id: object::new(ctx) , mintlist: table::new(ctx) };
let mut store = VoteStore {
id: object::new(ctx),
proposals: object_table::new(ctx),
};
let proposal = Proposal {
id: object::new(ctx),
votes: 0,
};
let (treasury_cap, meta) = coin::create_currency(waitness,6,b"VOTE", b"VOTE", b"", option::none(), ctx);
let vote_cap = Votecap { id: object::new(ctx), cap: treasury_cap };
object_table::add(&mut store.proposals, name, proposal);
public_freeze_object(meta);
share_object(vote_cap);
share_object(mintlist);
share_object(store);
}
public entry fun mint(
vote_cap: &mut Votecap,
mint_list: &mut Mintlist,
ctx: &mut TxContext
){
let addr = ctx.sender();
assert!(!table::contains(&mint_list.mintlist, addr), 1);
let coin = coin::mint(&mut vote_cap.cap, 100, ctx);
table::add(&mut mint_list.mintlist, addr, 100);
public_transfer(coin, addr);
}
public entry fun register_voter<T>(vote_coin: coin::Coin<T>, ctx: &mut TxContext) {
let amount = vote_coin.value();
assert!(amount == 100,1);
let sender = tx_context::sender(ctx);
let token = VoteToken<T> {
id: object::new(ctx),
amount: 100,
};
public_transfer(token, sender);
public_transfer(vote_coin, @0x0);
}
public entry fun vote<T>(token: &VoteToken<T>, store: &mut VoteStore, proposal_name: String) {
assert!(token.amount > 0, 1);
assert!(object_table::contains(&store.proposals, proposal_name), 2);
let proposal = object_table::borrow_mut(&mut store.proposals, proposal_name);
proposal.votes = proposal.votes + token.amount;
}
}