帕金森定律

帕金森十大定律

来源:百度百科

定律1——冗员增加原理:

  • 官员数量增加与工作量并无关系,而是由两个源动因造成的。每一个官员都希望增加部属而不是对手(如“投票”);
  • 官员们彼此为对方制造工作

定律2——中间派决定原理:

中间派是指对决定的内容不十分清楚的、意志薄弱、耳朵不大灵光的人,他们在组织的“票决制”议程中具有举足轻重的作用。为了争取中间派的支持,双方颇费心机进行争取,特别是双方势均力敌的情况下。所以,不是竞争对手而是中间派成了主角。

定律3——鸡毛蒜皮定律:

大部分官员由不懂得百万、千万元而只懂得千元的人组成,以至于讨论各种财政议案所费的时间与涉及的金额呈反比,即涉及的金额越大,讨论的时间越短,反之时间则越长,越是鸡毛蒜皮的事情越花费很多时间。

定律4——无效率系数:

由于复杂的利益关系,决策性委员会多的非必要成员愈来愈多,以至于会议开始变质,变得效率低下。于是,不得不在委员会重新设立核心决策委员会或核心决策团体。

定律5——人事遴选庸才:

人们设计了许多的人事遴选方法,但大部分测试都是徒劳无功的,最终不得不靠偶然性标准遴选。

定律6——办公场合的豪华程度与机关的事业和效率呈反比:

事业处于成长期的机关一般没有足够的兴趣和时间设计完美无缺的总部。所以,“设计完美乃是凋零的象征”,“完美就是结局,结局就是死亡”。

定律7——鸡尾酒会公式:

会议与鸡尾酒会(饭局)同在,不同重要性的人物参加鸡尾酒会,会在不同的时间出现,并站在不同的位置上。把会场从左到右分为A-F六段,从进门处到最远端分为1-8八段,则可划分出48个区域;在假定酒会开始的时间为H,且最后一名客人离开的时间是最初一名客人进场后2小时20分钟,则,重要人物都会在H+75至H+90的时间在E/7区域集合,最重要的人物自然会在其中。

定律8——嫉妒症(分三个时期):

在嫉妒症流行的机关里,高级主管辛苦而迟钝,中层干部勾心斗角,底层人员垂头丧气而不务正业。

  • 第一阶段,出现了既无能又好嫉妒的人物,即患上了“庸妒症(平庸而嫉妒)”;
  • 第二阶段,这些庸妒症患者不幸进入或原本就在高层,尽一切可能手段排斥比自己强的人,拒绝提升能力强的人;“愚蠢比赛”;
  • 第三阶段,机关仿佛被喷了DDT,凡才智者一概不得入内,机关病入膏肓,此时的机关已经无药可救了。

定律9——财不外露

财不外露

定律10——延迟退休:

一般退休的年龄是R,在前3年(R-3)人的精力会开始减退;问题在于如何挑选合适的接替者,工作表现越优秀,任职时间越长,越难寻得合适的接替者,而在位者总会设法阻止职位较低的人接近自己的职位,以至不得不延长自己的退休时间。

如何预防?

  • 建立学习型的组织,持续学习新东西
  • 招聘人员要公开透明,不能全权交由直接上级,防止招聘能力低下的人
  • 建立人才培养计划
  • 定期考核

分析可升级智能合约

准备

为了理解可升级合约,必须理解proxy机制,要理解proxy机制,必须理解solidity的sstoresload,以及关于以太坊架构和存储结构(数据结构)。

关于Solidity中的sstoresload深入理解:

简单概括一下:

  • sstore将一对key-value存入storage
  • sload按照key取出storage中的value
  • 一笔交易中可以多次sstoresload
  • key一般用slot(槽)代替,是32bytes的哈希
  • 以上的storage是某一个合约下面的storage

合约代码分析

基于solidity ^0.4.24

其中Proxy:

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
// 抽象合约
contract Proxy {

// fallback函数
function () payable external {
_fallback();
}

// 虚函数,需要子类实现
function _implementation() internal view returns (address);

// 以下是proxy合约通用代码,
function _delegate(address implementation) internal {
assembly {
// 将msg.data,即交易的所有数据,复制到内存
calldatacopy(0, 0, calldatasize)

// 调用实现合约
let result := delegatecall(gas, implementation, 0, calldatasize, 0, 0)

// 将返回数据拷贝到内存
returndatacopy(0, 0, returndatasize)

switch result
case 0 { revert(0, returndatasize) } // 0,失败
default { return(0, returndatasize) } // 1, 成功
}
}

// 子类可以重写次函数
function _willFallback() internal {
}

// fallback函数实现
function _fallback() internal {
_willFallback();
_delegate(_implementation());
}
}
  • calldatacopy(t, f, s):将calldata(输入数据)从位置f开始复制s字节到mem(内存)的位置t。
  • delegatecall(g, a, in, insize, out, outsize):调用地址a的合约,输入为mem[in..(in+insize)) ,输出为mem[out..(out+outsize)), 提供g的gas 和v wei的以太坊。这个操作码在错误时返回0,在成功时返回1。
  • returndatacopy(t, f, s):将returndata(输出数据)从位置f开始复制s字节到mem(内存)的位置t。
  • switch:基础版if/else,不同的情况case返回不同值。可以有一个默认的default情况。
  • return(p, s):终止函数执行, 返回数据mem[p..(p+s))。
  • revert(p, s):终止函数执行, 回滚状态,返回数据mem[p..(p+s))。

参考代理合约: https://blog.csdn.net/weixin_30230009/article/details/127312438

示例

理解了代理(可升级)合约机制之后,我们动手实践一下

实现合约(implement):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

contract Storage {

uint256 number;

function store(uint256 num) public {
number = num;
}

function retrieve() public view returns (uint256){
return number;
}
}

代理合约:

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
// SPDX-License-Identifier: None

pragma solidity ^0.8.0;

library AddressUtils {

/**
* Returns whether the target address is a contract
* @dev This function will return false if invoked during the constructor of a contract,
* as the code is not actually created until after the constructor finishes.
* @param addr address to check
* @return whether the target address is a contract
*/
function isContract(address addr) internal view returns (bool) {
uint256 size;
// XXX Currently there is no better way to check if there is a contract in an address
// than to check the size of the code at that address.
// See https://ethereum.stackexchange.com/a/14016/36603
// for more details about how this works.
// TODO Check this again before the Serenity release, because all addresses will be
// contracts then.
// solium-disable-next-line security/no-inline-assembly
assembly { size := extcodesize(addr) }
return size > 0;
}

}
abstract contract Proxy {
/**
* @dev Fallback function.
* Implemented entirely in `_fallback`.
*/
fallback() payable external {
_fallback();
}

receive() payable external {

}

/**
* @return The Address of the implementation.
*/
function _implementation() public virtual view returns (address);

/**
* @dev Delegates execution to an implementation contract.
* This is a low level function that doesn't return to its internal call site.
* It will return to the external caller whatever the implementation returns.
* @param implementation Address to delegate.
*/
function _delegate(address implementation) internal {
assembly {
// Copy msg.data. We take full control of memory in this inline assembly
// block because it will not return to Solidity code. We overwrite the
// Solidity scratch pad at memory position 0.
calldatacopy(0, 0, calldatasize())

// Call the implementation.
// out and outsize are 0 because we don't know the size yet.
let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)

// Copy the returned data.
returndatacopy(0, 0, returndatasize())

switch result
// delegatecall returns 0 on error.
case 0 { revert(0, returndatasize()) }
default { return(0, returndatasize()) }
}
}

/**
* @dev Function that is run as the first thing in the fallback function.
* Can be redefined in derived contracts to add functionality.
* Redefinitions must call super._willFallback().
*/
function _willFallback() internal {
}

/**
* @dev fallback implementation.
* Extracted to enable manual triggering.
*/
function _fallback() internal {
_willFallback();
_delegate(_implementation());
}
}

contract TestSstore is Proxy {

bytes32 private constant IMPLEMENTATION_SLOT = 0x7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c3;

constructor(address implementation_) {
assert(IMPLEMENTATION_SLOT == keccak256("org.zeppelinos.proxy.implementation"));

setImplementation(implementation_);
}

function _implementation() public override view returns (address impl) {
bytes32 slot = IMPLEMENTATION_SLOT;
assembly {
impl := sload(slot)
}
}


function setImplementation(address newImplementation) public {
require(AddressUtils.isContract(newImplementation), "Cannot set a proxy implementation to a non-contract address");

bytes32 slot = IMPLEMENTATION_SLOT;

assembly {
sstore(slot, newImplementation)
}
}

}
  • 部署代理合约(Proxy)时候, 需要填写实现合约(implement)的地址
  • 为了获得调用代理合约的数据,可以先在remix里面调用实现合约,在Metamask中拿到数据,然后粘贴到代理合约调用处

示例:

总结

通过delegatecall进行调用实现合约,数据是存放在代理合约中,因此当“升级”实现合约合约后,不会影响现有的数据。

delegatecall很像“动态库”


关于delegatecallcall的对比:

Rust借用分析

可以把Rust中的借用,理解为C语言中的指针, mut, &, 可变借用、不可变借用这些比较绕的概念,可以理解为C语言中的const修饰符(尽管,C语言中的const只是做一个“约定”, 这里只是为了方便理解, 不必纠结)。

例如 let b = 1; let a = &b; , a是指向不可变变量b不可变借用

我们用C语言的可以表示为: const int b = 1; const int const *a = &b;


第1种

1
2
3
4
5
6
7
8
9
10
11

let b = 1;
let a = b;

println!("a = {} ", a);
println!("b = {}", b);
// println!("*a = {}", *a); // error: type `{integer}` cannot be dereferenced

let c = 2;
// a = c; // error: cannot assign twice to immutable variable

  • let a = b; 是将b的值拷贝给a。 注意,不是移动!
  • ab一样, 也是不可变的整型变量a不是b引用,也不是b的move

第2种

1
2
3
4
5
6
let b = 2;
let a = &b;
println!("a = {}, b = {}", a, b);
println!("a = {}, b = {}", *a, b);

// *a = 99; // `a` is a `&` reference, so the data it refers to cannot be written
  • b不可变整型变量
  • ab不可变引用, 因此*a(即a所引用的内容)不能被修改

第3种

1
2
3
4
5
6
7
8
9
let b = 2;
let mut a = &b;
println!("a = {}, b = {}", a, b); // ok, 自动解引用
println!("*a = {}, b = {}", *a, b); // ok,手动解引用

let c = 3;
a = &c; // 修改 a 的指向
println!("a = {}", a);

可以将引用理解为C语言中的指针, 很像 const修饰的原理

  • let mut a = &b; 其中 a是指向不可变变量b可变引用, 即b的内容不能被改变, 但是,a本身的“指向”可以变
  • a = &c; 即改变了 a的指向, a指向了c

第4种

1
2
let b = 1;
let a = &mut b; // error: cannot borrow `b` as mutable, as it is not declared as mutable

不能对不可变变量进行可变借用

1
2
3
4
5
6
7
8
9
10
11
12
13

let mut b = 1;
let a = &mut b;
println!("xxx===> a = {}", a);
// println!("xxx===> a = {}, b = {}", a, b); // error, 不能同时可变引用和不可引用
// println!("b = {}", b); //error, 不能同时可变引用和不可引用
*a = 99;
// println!("xxx===> a = {}, b = {}", a, b); // error, 不能同时可变引用和不可引用
println!("xxx===> a = {}", a);
println!("b = {}", b); // 可变引用用完了, 原来的不可变引用可以继续使用了

let mut c = 1;
// a = &mut c; // error, cannot assign twice to immutable variable `a`
  • a是指向可变变量b不可变引用, 即a的指向不能变, 所指向的内容(值)*a是可以变的

第5种

1
2
3
4
5
let b = 1;
let mut a = b; // 将b的值进行了拷贝
println!("===> a = {}, b = {}", a, b);
a = 2;
println!("===> a = {}, b = {}", a, b);
  • let mut a = b; 是将b的值拷贝到a, 不是move! 因此,互不影响
  • a可变整型变量

第6种

1
2
3
4
5
6
let b = 1;
let &(mut a) = &b;
println!("+++ a = {}, b = {}", a, b);
a = 999;
println!("+++ a = {}, b = {}", a, b);
// println!("+++ a = {}, b = {}", *a, b); // type `{integer}` cannot be dereferenced
  • let &(mut a) = &b; 可以“约”多余符号,等效于 let mut a = b;, 因此效果同上例(第5种), 不赘述

第7种

1
2
3
4
5
6
7
8
9

let mut c = 1;
let mut a = &mut c;
*a = 99;
println!("a = {}", *a);

let mut d = 33;
a = &mut d; // ok
println!("a = {}", *a);
  • 如果理解上面提到集中情况, 很容易理解此种变化
  • a 是指向 可变整型变量c可变整型变量的可变引用
  • 两个“可变”即代表, a所指向内容(*a)是可以修改的; 同时,a本身的“指向”也是可以修改的

第8种

1
2
3
4
5
6
7
8
9
10
11
12
13
let b = 1;
// let ref mut a = b; // 错,同 let a = &mut b;
let mut c = 1;
let ref mut a = c; // 等效于 let a = &mut c;
*a = 99;
// println!("a = {}, c = {}", *a, c); // error, c已经被可变借用了,不能和可变借用同时存在
println!("a = {}", *a);
println!("c = {}", c); // 可变借用用完之后, c不可变引用又可以使用了

let mut d = 777;
// a = &mut d; // error, cannot assign twice to immutable variable `a`
// println!("a = {}", a);

  • let ref mut a = c; 等效于 let a = &mut c;

东南亚Web3调研

印度尼西亚

互联网的发展

  • 走近印尼:一个痴迷Web3.0的国家: https://36kr.com/p/1858243116275592
  • 印尼市场报告:机会飙升、社媒蓬勃、中小网红崛起,印尼或将进入数字十年: https://www.cifnews.com/article/122041
    • 据We Are Social数据显示,2022 年初,印度尼西亚的互联网用户达到 2.047 亿人,这个数据意味着,印尼的互联网用户比前一年增加了 210 万,互联网普及率为73.7%,成为东南亚互联网用户增长较快的地区之一。
    • 社交媒体用户的中位年龄为30.3岁。
    • 社交软件: Whatsapp, Youtube, Facebook, Instagram, Tiktok
  • 2022年东南亚电商数据报告: https://www.cifnews.com/article/132187
  • 2022年印度尼西亚移动互联网报告: http://www.199it.com/archives/1422699.html
    • 2021年,印尼的新应用下载量超过73亿次,比2019年大流行前的水平增长了33%。
    • 应用商店消费者支出自2019年以来增长了38%,到2021年超过每分钟1000美元。
    • 前20大视频流媒体应用的总访问时间为270亿小时,自2019年以来增长了93%,是全球增长率的3倍。
    • 热门应用包括YouTube、MX Player、Netflix、YouTube Kids 和Viu 等全球品牌. 另一个在印尼的总使用时长显著增长的类别是购物应用程序。
    • 自2019年以来,花在零售应用上的时间从20亿小时增加到2021年的近56亿小时,增长了180%。
    • 2021年,印尼的金融应用下载量超过3.82亿次,同比增长82%,自2018年以来增长185%。

e-Conomy SEA 2022

谷歌关于东南亚数字经济的研究报告-2022版

报告的几个关键点:

  • 东南亚主要的6个国家(越南、泰国、马来西亚、新加坡、印尼、菲律宾),总人口超6亿
  • 其中菲律宾越南在SaaS和Web3领域的增长最快
  • 东南亚的“数字10年”才刚刚起步,预计到2025年东南亚的数字经济规模将达到3000亿美元,预计到2030年数字经济规模将会超过6000亿美元
  • 城市中等收入人群中18~29岁的年轻人占比为11%, 城市高收入人群整体占比18%
  • 东南亚的数字经济规模达到2000亿美元,比预期提前3
  • 数字银行和Web3领域的投资的过去一年增长了1
  • SaaS和Web3是东南亚解决新的挑战的关键所在
  • 东南亚的SaaS、软件产业、Web3将在未来3~8年增长80%
  • 将Web3嵌入到现有的Web2平台是发展的趋势
  • 嵌入金融服务的SaaS解决方案是提升中小企业的数字化和专业化的关键
  • VC在Web3领域的投资在持续增加,以下是VC投资领域的占比:
    • 隐私和数字基础设施: 67%
    • DeFi: 57%
    • 区块链游戏: 37%
    • DAOs: 27%
    • 元宇宙: 27%
    • NFTs: 13%
  • 远程教育在疫情之后降温,投资者更多的转向SaaS和Web3领域

东南亚的Web3

  • 印尼在加密货币领域占比是最高, 占总人口的2.66%(约700万人), 交易金额超过250亿美元: https://techcollectivesea.com/2022/05/09/web3-in-southeast-asia/

  • 新加坡

  • 越南,超过20%越南人买加密货币

  • 菲律宾,国家承认加密货币

  • 越南拥抱web3:https://www.f6ex.com/archives/84164.html

  • https://meet.bnext.com.tw/articles/view/49354?

    • 東南亞也是全球最年輕、最具活力,最積極擁抱數位應用的地區,人口年齡中位數為30歲
    • 在東南亞近7億人口的大市場中,超過70%的民眾缺乏銀行服務(Underbanked)或無銀行帳號(Unbanked),這樣的條件,為DeFi、加密貨幣投資或資產管理提供了絕佳的發展條件,在提供給大眾的金融服務上,用戶將很輕易跳過傳統銀行直接進入Web3。
    • 在NFT的應用發展上,東南亞也居於領先地位,根據Statista統計,泰國擁有565萬名用戶、越南219萬名、印尼125萬名,分別位居全球第1、5、8名。
  • https://accesspath.com/tech/crypto-blockchain/5705430/

EIP1967-实现可升级智能合约

EIP1967-实现可升级智能合约

EIP1967实现可升级的合约(逻辑和数据存储分离)

https://eips.ethereum.org/EIPS/eip-1967

解决upgrade-safe
https://docs.openzeppelin.com/upgrades-plugins/1.x/faq#what-does-it-mean-for-a-contract-to-be-upgrade-safe

通过使用逻辑处理与存储分离的模式,来实现智能合约升级。

通过以下代码进行理解

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
contract Proxy {
mapping(address => uint) private balances; // 余额

address private impl;

function upgradeTo(address _addr) {
impl = _addr;
}

// 当调用的代理
fallback() external payable virtual {
_fallback();
}
function _fallback() internal virtual {
_beforeFallback();
_delegate(_implementation());
}


// 调用
function _delegate(address implementation) internal virtual {
assembly {
// Copy msg.data. We take full control of memory in this inline assembly
// block because it will not return to Solidity code. We overwrite the
// Solidity scratch pad at memory position 0.
calldatacopy(0, 0, calldatasize())

// Call the implementation.
// out and outsize are 0 because we don't know the size yet.
let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)

// Copy the returned data.
returndatacopy(0, 0, returndatasize())

switch result
// delegatecall returns 0 on error.
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
}

部署

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

const { ethers, upgrades } = require("hardhat");

async function main() {

// acc = ethers.getSigners()
const [owner] = await ethers.getSigners();

// Deploying
const sbt = await ethers.getContractFactory("SBT");
const instance = await upgrades.deployProxy(
sbt,
[
"Soulbound Token",
"SBT",
owner.address,
],
{
initializer: "initialize",
kind: "transparent",
unsafeAllow: ['delegatecall'] // 遇到unsafe upgrade错误,可以强行使用
}
);

let ret = await instance.deployed();
console.log(ret)

// await upgradeProxy(proxyAddress, implementationFactory, { unsafeAllow: ['delegatecall'] });

// Upgrading
// const BoxV2 = await ethers.getContractFactory("BoxV2");
// const upgraded = await upgrades.upgradeProxy(instance.address, BoxV2);
}

main();
  • Copyrights © 2021-2024 youngqqcn

请我喝杯咖啡吧~