0xmonaco CTF 体验心得
由开发人员、艺术家和设计师组成的集体 MatchBoxDAO 宣布推出 MatchBox Arena。该团队将其称为“Web3 公司的世界杯”,并表示游戏锦标赛旨在找出哪家公司拥有最好的技术团队。首先,可以代表公司和世界顶级的crypto公司(uniswap,polygon,ledger,chainlink。。。)同台竞技真的是一个非常荣幸的事情。所以我牺牲了宝贵的春节假期,就一直在打这个比赛。 这次CTF是一个用solidity操控汽车的算法比赛(终于遇到我非常感兴趣的地方了)介绍这本质上来说是一次博弈实验,而不是一次简单的代码hackthon。更像是一个社会实验,涉及纯技术方面、经济激励、效用优化模式和理性的压力测试。对于每一个参赛者,你需要实现自己的Car合约,特别是takeyourturn这个函数。对于每一轮你都需要做出决策,具体有五种决策: 1)加速(ACCELERATE) 2)炮弹(SHELL) 3)超级炮弹(SUPER_SHELL) 4)香蕉(BANANA) 5)盾(SHIELD) 有点像跑跑卡丁车?是的。。每一种决策都会耗费掉你的金额,你的金额总量是17500。而...

成长 -- 随笔(2)
深夜陷入了沉思,回顾了一下自己的成长历程。距离上一次的成长随笔已经过去7个月了~~ https://mirror.xyz/0xaaE7a1AD2764626d09a233a9bC06C38b413637cf/By3P_3NiIriKGObdbWlFo0mDdwFDY1v9VFbjaUMmObU 既然是随笔,我觉得格式什么的,就随意了~~ 这段时间我学了啥呢~~ Uniswap V2, V3; 精通Curve ( 3 Pool, Meta Pool, Compond Pool, AAVE Pool) ~~~ Balancer V2, Kyber, Bancor ; AAVE, Clipper, DODO, Mstable, Saddle, Shell, Wombat ~~~ DODO, DODO V2, Fraxswap ~~ 对我来说,能力提升最大的是打CTF。比赛的过程,纠错发现bug的攻防真的很能提升一个人的合约能力~~~ 最开心的是,认识了组内Andrew和Jimmy两位Crypto科学家~~ 最感激的是,Melvin带着我做项目,耐心和孜孜不倦地引导我去激发自己的潜能~~...
成长 -- 随笔
我完全不敢想象自己的成长速度。 1个月前,我还在和慢雾的群上问curve的合约代码的语言是的时候。余弦大佬回了我是vyper。我现在已经可以把vyper语言看懂了, 并且对于原理也掌握了。 把curve代码看了一下一遍,其实也发现不过如此。白皮书,其实也没这么深奥。跟当年打ACM的那种级别比,还是差得有点远。 Hardhat也越来越熟悉了。当时那个编写测试用例还要问XD的那个毛头小子,已经成长了好多。 我觉得我现在完全可以独立撑起一个商业项目,唯一卡住的地方可能是JS还是不太熟悉。基本功能是OK的,但是遇到一些比较少见的bug。估计,要问人。 对于以前的我来说,3,4天吃透一个主流Defi协议,我真的想都不敢想。如果只是调研,我觉得我还是勉强可以一试。 这种成长的速度我只能用指数级别来形容。我看了一下一个月前的自己,觉得好菜。 我很希望我一个月之后,再回头看现在的我,也是觉得现在的我很菜~~ end
0xmonaco CTF 体验心得
由开发人员、艺术家和设计师组成的集体 MatchBoxDAO 宣布推出 MatchBox Arena。该团队将其称为“Web3 公司的世界杯”,并表示游戏锦标赛旨在找出哪家公司拥有最好的技术团队。首先,可以代表公司和世界顶级的crypto公司(uniswap,polygon,ledger,chainlink。。。)同台竞技真的是一个非常荣幸的事情。所以我牺牲了宝贵的春节假期,就一直在打这个比赛。 这次CTF是一个用solidity操控汽车的算法比赛(终于遇到我非常感兴趣的地方了)介绍这本质上来说是一次博弈实验,而不是一次简单的代码hackthon。更像是一个社会实验,涉及纯技术方面、经济激励、效用优化模式和理性的压力测试。对于每一个参赛者,你需要实现自己的Car合约,特别是takeyourturn这个函数。对于每一轮你都需要做出决策,具体有五种决策: 1)加速(ACCELERATE) 2)炮弹(SHELL) 3)超级炮弹(SUPER_SHELL) 4)香蕉(BANANA) 5)盾(SHIELD) 有点像跑跑卡丁车?是的。。每一种决策都会耗费掉你的金额,你的金额总量是17500。而...

成长 -- 随笔(2)
深夜陷入了沉思,回顾了一下自己的成长历程。距离上一次的成长随笔已经过去7个月了~~ https://mirror.xyz/0xaaE7a1AD2764626d09a233a9bC06C38b413637cf/By3P_3NiIriKGObdbWlFo0mDdwFDY1v9VFbjaUMmObU 既然是随笔,我觉得格式什么的,就随意了~~ 这段时间我学了啥呢~~ Uniswap V2, V3; 精通Curve ( 3 Pool, Meta Pool, Compond Pool, AAVE Pool) ~~~ Balancer V2, Kyber, Bancor ; AAVE, Clipper, DODO, Mstable, Saddle, Shell, Wombat ~~~ DODO, DODO V2, Fraxswap ~~ 对我来说,能力提升最大的是打CTF。比赛的过程,纠错发现bug的攻防真的很能提升一个人的合约能力~~~ 最开心的是,认识了组内Andrew和Jimmy两位Crypto科学家~~ 最感激的是,Melvin带着我做项目,耐心和孜孜不倦地引导我去激发自己的潜能~~...
成长 -- 随笔
我完全不敢想象自己的成长速度。 1个月前,我还在和慢雾的群上问curve的合约代码的语言是的时候。余弦大佬回了我是vyper。我现在已经可以把vyper语言看懂了, 并且对于原理也掌握了。 把curve代码看了一下一遍,其实也发现不过如此。白皮书,其实也没这么深奥。跟当年打ACM的那种级别比,还是差得有点远。 Hardhat也越来越熟悉了。当时那个编写测试用例还要问XD的那个毛头小子,已经成长了好多。 我觉得我现在完全可以独立撑起一个商业项目,唯一卡住的地方可能是JS还是不太熟悉。基本功能是OK的,但是遇到一些比较少见的bug。估计,要问人。 对于以前的我来说,3,4天吃透一个主流Defi协议,我真的想都不敢想。如果只是调研,我觉得我还是勉强可以一试。 这种成长的速度我只能用指数级别来形容。我看了一下一个月前的自己,觉得好菜。 我很希望我一个月之后,再回头看现在的我,也是觉得现在的我很菜~~ end

Subscribe to shaneson.eth

Subscribe to shaneson.eth
Share Dialog
Share Dialog
<100 subscribers
<100 subscribers
Move语言里,最高级和最难掌握的用法是泛型。它是 Move 灵活性的重要来源,融合C++的泛型编程的思想。与Solidity对比,泛型的功能可以让工厂合约更容易实现合约模版,提供了非常强的灵活性。本文会介绍,我在学习Move泛型编程时的要点。
通过泛型的定义,我们可以使得value的值可以是任何的类型T。
module Storage {
struct Box<T> {
value: T
}
}
我以create Box为例,构造一个模版方法和get 方法。
module ShanesonStudy::Generics {
struct Box<T> has drop, copy, key {
value: T
}
public fun create_box<T>(value: T): Box<T> {
Box<T> { value }
}
public fun value<T: copy> (box: &Box<T>): T {
*&box.value
}
}
create_box的模版参数为T,假设传入的值为value,类型为T。那么语法就是create_box (value: T),返回值是Box。这里值得注意的是,临时变量是要被丢弃的。所以,struct Box要有Drop权限。 方法value看起来非常复杂,意思就是:“就是把Box里面的value拷贝出来一份”。 测试方法: module ShanesonStudy::GenericsTest {
use ShanesonStudy::Generics as G;
use std::debug as D;
#[test]
public entry fun create_box_test() {
let _box = G::create_box<bool>(true);
let _box_val = G::value(&_box);
D::print<bool> (&_box_val);
assert!(_box_val, 0);
let u64_box = G::create_box<u64> (1000000);
let _u64_box_result = G::value(&u64_box);
D::print<u64>(&_u64_box_result);
}
}
Result: Abilities限制符 泛型里的模版参数也是有限制的,所以可以在模版定义的时候定义它的权限:“copy + drop” fun name<T: copy>() {} // allow only values that can be copied
fun name<T: copy + drop>() {} // values can be copied and dropped
fun name<T: key + store + drop + copy>() {} // all 4 abilities are present
struct name<T: copy + drop> { value: T } // T can be copied and dropped
struct name<T: stored> { value: T } // T can be stored in global storage
注意,尽可能使泛型参数的限制符和结构体本身的abilities显示的保持一致。+号很少使用,但是这里确实是+号来拼接限制符。 所以下面这种定义的方法更安全:
// we add parent's constraints
// now inner type MUST be copyable and droppable
struct Box<T: copy + drop> has copy, drop {
contents: T
}
多类型限制符 我们也可以在泛型中使用多个类型,像使用单个类型一样,把多个类型放在尖括号中,并用逗号分隔。我们来试着添加一个新类型Shelf,它将容纳两个不同类型的Box。 module Storage {
struct Box<T> {
value: T
}
struct Shelf<T1, T2> {
box_1: Box<T1>,
box_2: Box<T2>
}
public fun create_shelf<Type1, Type2>(
box_1: Box<Type1>,
box_2: Box<Type2>
): Shelf<Type1, Type2> {
Shelf {
box_1,
box_2
}
}
}
Shelf的类型参数需要与结构体字段定义中的类型顺序相匹配,而泛型中的类型参数的名称则无需相同,选择合适的名称即可。正是因为每种类型参数仅仅在其作用域范围内有效,所以无需使用相同的名字。 多类型泛型的使用与单类型泛型相同: script {
use {{sender}}::Storage;
fun main() {
let b1 = Storage::create_box<u64>(100);
let b2 = Storage::create_box<u64>(200);
// you can use any types - so same ones are also valid
let _ = Storage::create_shelf<u64, u64>(b1, b2);
}
}
并非泛型中指定的每种类型参数都必须被使用。看这个例子: module Storage {
// these two types will be used to mark
// where box will be sent when it's taken from shelf
struct Abroad {}
struct Local {}
// modified Box will have target property
struct Box<T, Destination> {
value: T
}
public fun create_box<T, Dest>(value: T): Box<T, Dest> {
Box { value }
}
}
也可以在脚本中使用 :
script {
use {{sender}}::Storage;
fun main() {
// value will be of type Storage::Box<bool>
let _ = Storage::create_box<bool, Storage::Abroad>(true);
let _ = Storage::create_box<u64, Storage::Abroad>(1000);
let _ = Storage::create_box<u128, Storage::Local>(1000);
let _ = Storage::create_box<address, Storage::Local>(0x1);
// or even u64 destination!
let _ = Storage::create_box<address, u64>(0x1);
}
}
Move语言里,最高级和最难掌握的用法是泛型。它是 Move 灵活性的重要来源,融合C++的泛型编程的思想。与Solidity对比,泛型的功能可以让工厂合约更容易实现合约模版,提供了非常强的灵活性。本文会介绍,我在学习Move泛型编程时的要点。
通过泛型的定义,我们可以使得value的值可以是任何的类型T。
module Storage {
struct Box<T> {
value: T
}
}
我以create Box为例,构造一个模版方法和get 方法。
module ShanesonStudy::Generics {
struct Box<T> has drop, copy, key {
value: T
}
public fun create_box<T>(value: T): Box<T> {
Box<T> { value }
}
public fun value<T: copy> (box: &Box<T>): T {
*&box.value
}
}
create_box的模版参数为T,假设传入的值为value,类型为T。那么语法就是create_box (value: T),返回值是Box。这里值得注意的是,临时变量是要被丢弃的。所以,struct Box要有Drop权限。 方法value看起来非常复杂,意思就是:“就是把Box里面的value拷贝出来一份”。 测试方法: module ShanesonStudy::GenericsTest {
use ShanesonStudy::Generics as G;
use std::debug as D;
#[test]
public entry fun create_box_test() {
let _box = G::create_box<bool>(true);
let _box_val = G::value(&_box);
D::print<bool> (&_box_val);
assert!(_box_val, 0);
let u64_box = G::create_box<u64> (1000000);
let _u64_box_result = G::value(&u64_box);
D::print<u64>(&_u64_box_result);
}
}
Result: Abilities限制符 泛型里的模版参数也是有限制的,所以可以在模版定义的时候定义它的权限:“copy + drop” fun name<T: copy>() {} // allow only values that can be copied
fun name<T: copy + drop>() {} // values can be copied and dropped
fun name<T: key + store + drop + copy>() {} // all 4 abilities are present
struct name<T: copy + drop> { value: T } // T can be copied and dropped
struct name<T: stored> { value: T } // T can be stored in global storage
注意,尽可能使泛型参数的限制符和结构体本身的abilities显示的保持一致。+号很少使用,但是这里确实是+号来拼接限制符。 所以下面这种定义的方法更安全:
// we add parent's constraints
// now inner type MUST be copyable and droppable
struct Box<T: copy + drop> has copy, drop {
contents: T
}
多类型限制符 我们也可以在泛型中使用多个类型,像使用单个类型一样,把多个类型放在尖括号中,并用逗号分隔。我们来试着添加一个新类型Shelf,它将容纳两个不同类型的Box。 module Storage {
struct Box<T> {
value: T
}
struct Shelf<T1, T2> {
box_1: Box<T1>,
box_2: Box<T2>
}
public fun create_shelf<Type1, Type2>(
box_1: Box<Type1>,
box_2: Box<Type2>
): Shelf<Type1, Type2> {
Shelf {
box_1,
box_2
}
}
}
Shelf的类型参数需要与结构体字段定义中的类型顺序相匹配,而泛型中的类型参数的名称则无需相同,选择合适的名称即可。正是因为每种类型参数仅仅在其作用域范围内有效,所以无需使用相同的名字。 多类型泛型的使用与单类型泛型相同: script {
use {{sender}}::Storage;
fun main() {
let b1 = Storage::create_box<u64>(100);
let b2 = Storage::create_box<u64>(200);
// you can use any types - so same ones are also valid
let _ = Storage::create_shelf<u64, u64>(b1, b2);
}
}
并非泛型中指定的每种类型参数都必须被使用。看这个例子: module Storage {
// these two types will be used to mark
// where box will be sent when it's taken from shelf
struct Abroad {}
struct Local {}
// modified Box will have target property
struct Box<T, Destination> {
value: T
}
public fun create_box<T, Dest>(value: T): Box<T, Dest> {
Box { value }
}
}
也可以在脚本中使用 :
script {
use {{sender}}::Storage;
fun main() {
// value will be of type Storage::Box<bool>
let _ = Storage::create_box<bool, Storage::Abroad>(true);
let _ = Storage::create_box<u64, Storage::Abroad>(1000);
let _ = Storage::create_box<u128, Storage::Local>(1000);
let _ = Storage::create_box<address, Storage::Local>(0x1);
// or even u64 destination!
let _ = Storage::create_box<address, u64>(0x1);
}
}
No activity yet