由 Sui 赞助,MoveBit 等主办的大型 Move 安全竞赛 MoveCTF 已经结束。ComingChat 团队的三名参赛选手皆答对了全部题目,均获得满分成绩!
查看竞赛分数排名:
https://movectf.movebit.xyz/scoreboard
以下为 ComingChat 团队提供的竞赛题目满分答案:
第一题:
/ SPDX-License-Identifier: Apache-2.0
// Based on: https://github.com/starcoinorg/starcoin-framework-commons/blob/main/sources/PseudoRandom.move
/// @title pseudorandom
/// @notice A pseudo random module on-chain.
/// @dev Warning:
/// The random mechanism in smart contracts is different from
/// that in traditional programming languages. The value generated
/// by random is predictable to Miners, so it can only be used in
/// simple scenarios where Miners have no incentive to cheat. If
/// large amounts of money are involved, DO NOT USE THIS MODULE to
/// generate random numbers; try a more secure way.
module 0x0::test {
use std::hash;
use std::vector;
use sui::bcs;
use sui::tx_context::TxContext;
use game::hero::{Hero, level_up};
use game::adventure::{slay_boar, slay_boar_king};
use sui::object;
use game::inventory::{get_flag, TreasuryBox};
const ERR_HIGH_ARG_GREATER_THAN_LOW_ARG: u64 = 101;
public fun vector_slice<T: copy>(vec: &vector<T>, start: u64, end: u64): vector<T> {
let slice = vector::empty<T>();
let i = start;
while (i < end) {
vector::push_back(&mut slice, *vector::borrow(vec, i));
i = i + 1;
};
slice
}
public fun vector_to_u64(d: &vector<u8>): u64 {
let i = 0;
let m = 0;
let len = vector::length(d);
while (i < vector::length(d)) {
m = (m << 8) + ((*vector::borrow(d, len - 1 - i)) as u64);
i = i + 1;
};
m
}
public fun u64_to_vector(d: u64): vector<u8> {
bcs::to_bytes(&d)
}
public fun seed(ctx: &mut TxContext, m: u64): vector<u8> {
let ctx_bytes = bcs::to_bytes(ctx);
let tx_hash = vector_slice(&ctx_bytes, 21, 21 + ((*vector::borrow(&ctx_bytes, 20)) as u64));
let len = vector::length(&ctx_bytes);
let created_vector = vector_slice(&ctx_bytes, len - 8, len);
let created_num = vector_to_u64(&created_vector) + m;
let created_vector = u64_to_vector(created_num);
assert!(created_vector == u64_to_vector(created_num), 1);
let data = vector::empty<u8>();
vector::append(&mut data, vector_slice(&ctx_bytes, 0, len - 8));
vector::append(&mut data, created_vector);
let ctx_bytes = data;
let info: vector<u8> = vector::empty<u8>();
vector::append<u8>(&mut info, tx_hash);
vector::append<u8>(&mut info, created_vector);
let uid_bytes = vector_slice(&hash::sha3_256(info), 0, 20);
let info: vector<u8> = vector::empty<u8>();
vector::append<u8>(&mut info, ctx_bytes);
vector::append<u8>(&mut info, uid_bytes);
let hash: vector<u8> = hash::sha3_256(info);
hash
}
fun bytes_to_u64(bytes: vector<u8>): u64 {
let value = 0u64;
let i = 0u64;
while (i < 8) {
value = value | ((*vector::borrow(&bytes, i) as u64) << ((8 * (7 - i)) as u8));
i = i + 1;
};
return value
}
/// Generate a random u64
fun rand_u64_with_seed(_seed: vector<u8>): u64 {
bytes_to_u64(_seed)
}
/// Generate a random integer range in [low, high).
fun rand_u64_range_with_seed(_seed: vector<u8>, low: u64, high: u64): u64 {
assert!(high > low, ERR_HIGH_ARG_GREATER_THAN_LOW_ARG);
let value = rand_u64_with_seed(_seed);
(value % (high - low)) + low
}
/// Generate a random u64
public fun rand_u64(ctx: &mut TxContext): u64 {
rand_u64_with_seed(seed(ctx, 0))
}
/// Generate a random integer range in [low, high).
public fun rand_u64_range(low: u64, high: u64, ctx: &mut TxContext): u64 {
rand_u64_range_with_seed(seed(ctx, 0), low, high)
}
public entry fun win(hero: &mut Hero, ctx: &mut TxContext) {
let i = 0;
while (i < 125) {
slay_boar(hero, ctx);
i = i + 1;
};
level_up(hero);
let next = next_zero_rand_u64_range(0, 100, ctx) - 4;
while (next > 0) {
object::delete(object::new(ctx));
next = next - 1;
};
slay_boar_king(hero, ctx);
}
public fun next_zero_rand_u64_range(low: u64, high: u64, ctx: &mut TxContext): u64 {
let next = 0;
while (true) {
let data = rand_u64_range_with_seed(seed(ctx, next), low, high);
if ((data == 0) && (next >= 4)) {
break
};
next = next + 1;
};
next
}
public entry fun win_flag(box: TreasuryBox, ctx: &mut TxContext) {
let next = next_zero_rand_u64_range(0, 100, ctx);
while (next > 0) {
object::delete(object::new(ctx));
next = next - 1;
};
get_flag(box, ctx);
}
}
第二题:
module 0x0::test {
use sui::tx_context::TxContext;
use movectf::flash::{loan, FlashLender, deposit, check, withdraw, get_flag};
entry fun fight(
self: &mut FlashLender,
ctx: &mut TxContext
) {
let (coins, receipt) = loan(self, 1000, ctx);
deposit(self, coins, ctx);
check(self, receipt);
withdraw(self, 1000, ctx);
get_flag(self, ctx)
}
}
第三题:
module 0x0::test {
use sui::tx_context::TxContext;
use movectf::move_lock::{
movectf_unlock, get_flag, ResourceObject
};
entry fun fight(
r: &mut ResourceObject,
ctx: &mut TxContext
) {
let data1 = vector<u64>[
2, 14, 13,
6, 17, 0,
19, 20, 11,
0, 19, 8,
14, 13, 18,
24, 14, 20,
12, 0, 13,
0, 6, 4,
3, 19, 14,
1, 17, 4,
0, 10, 19,
7, 4, 7,
8, 11, 11,
2, 8, 15,
7, 4, 17,
7, 0, 2,
10, 19, 7,
4, 7, 0,
2, 10, 24,
15, 11, 0,
13, 4, 19
];
let data2 = vector<u64>[25, 11, 6, 10, 13, 25, 12, 19, 2];
movectf_unlock(data1, data2, r, ctx);
get_flag(r, ctx)
}
}
【免责声明】市场有风险,投资需谨慎。本文不构成投资建议,用户应考虑本文中的任何意见、观点或结论是否符合其特定状况。据此投资,责任自负。