3分钟Solidity: 3.4 用户定义值类型

26 阅读1分钟

如需获取本内容的最新版本,请参见 Cyfrin.io 上的“用户定义值类型(代码示例)”

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;

// Code copied from optimism
// https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/dispute/lib/LibUDT.sol

type Duration is uint64;

type Timestamp is uint64;

type Clock is uint128;

library LibClock {
    function wrap(Duration _duration, Timestamp _timestamp)
        internal
        pure
        returns (Clock clock_)
    {
        assembly {
            // data | Duration | Timestamp
            // bit  | 0 ... 63 | 64 ... 127
            clock_ := or(shl(0x40, _duration), _timestamp)
        }
    }

    function duration(Clock _clock)
        internal
        pure
        returns (Duration duration_)
    {
        assembly {
            duration_ := shr(0x40, _clock)
        }
    }

    function timestamp(Clock _clock)
        internal
        pure
        returns (Timestamp timestamp_)
    {
        assembly {
            timestamp_ := shr(0xC0, shl(0xC0, _clock))
        }
    }
}

// 无用户定义值类型的时钟库
library LibClockBasic {
    function wrap(uint64 _duration, uint64 _timestamp)
        internal
        pure
        returns (uint128 clock)
    {
        assembly {
            clock := or(shl(0x40, _duration), _timestamp)
        }
    }
}

contract Examples {
    function example_no_uvdt() external view {
        // 无用户定义值类型
        uint128 clock;
        uint64 d = 1;
        uint64 t = uint64(block.timestamp);
        clock = LibClockBasic.wrap(d, t);
        // 哎呀!输入顺序错了,但居然还能编译通过
        clock = LibClockBasic.wrap(t, d);
    }

    function example_uvdt() external view {
        // 将值类型转换为用户定义的值类型
        Duration d = Duration.wrap(1);
        Timestamp t = Timestamp.wrap(uint64(block.timestamp));
        // 将用户定义的值类型转换回原始值类型
        uint64 d_u64 = Duration.unwrap(d);
        uint64 t_u64 = Timestamp.unwrap(t);

        // LibClock 示例
        Clock clock = Clock.wrap(0);
        clock = LibClock.wrap(d, t);
        // 哎呀!输入顺序错了
        // 这不会编译
        // clock = LibClock.wrap(t, d);
    }
}

Remix Lite 尝试一下

solidity-用户定义值类型


END