JavaScript 开发人员的 Solidity 基础知识(第一部分)
随着 NFT 的热潮兴起,我恰好接到了撰写一篇关于 NFT 和无服务器的文章的任务。因此,过去三周,我深入研究了有关代币和智能合约的书籍、课程和视频。
这是一个令人兴奋的话题,我认为尽管代币经济存在缺点,但它可以成为互联网的下一步,成为我们目前面临的许多问题的解决方案。
但在这篇博文中,我不会深入探讨我的观点,也不会教你一些东西。我会解释一下用 Solidity 编写的智能合约,以及 JavaScript 的等效代码,以便更清晰地理解这些语言之间的一些主要区别。我不会在这里深入探讨;我想解释一下基础知识。
静态类型与动态类型
JavaScript 和 Solidity 之间的主要区别在于类型。Solidity 在构建时是静态类型的,而 JavaScript 是动态类型的。
原因在于,以太坊虚拟机(EVM)对计算和存储成本非常挑剔。所有费用都必须考虑在内,这样才能相应地收取费用。
JavaScript 的目标是更加易于使用。
JavaScript
let x = 10;
Solidity
int256 x = 10;
因此,Solidity 在这方面有点像 Java 或 C。
您还必须输入函数参数和返回值。
JavaScript
function f(a, b) {
return a + b;
}
Solidity
function f(int256 a, int256 b) returns (int256) {
return a + b;
}
如果您有更复杂的类型,如数组或结构体,则类型系统要求您定义数据所在的内存位置。
JavaScript
function f(a, b) {
let c = [];
for(let i = 0; i < a.length; i++) {
c[i] += a[i] + b;
}
return c;
}
Solidity
function f(int256[] calldata a, int256 b) returns (int256[] memory) {
int256[] memory c;
for(uint i = 0; i < a.length; i++) {
c[i] = a[i] + b;
}
return c;
}
这里我将第一个参数定义a
为一个数组,int256
并表示它应该存储在该calldata
位置。calldata
它不是持久的,不能被修改,而且我a
在函数中只读取它而从不写入它。
其他变量要么明确存储在该memory
位置,要么具有不需要定义位置的基本类型。
整数与数字
两种语言之间的另一个根本区别是它们的默认数字类型。JavaScript 使用number
,它始终是浮点数。Solidity 使用各种大小的int
。
其背后的想法是,Solidity 的核心是支付,如果你拥有一种每单位价值数千美元的货币,那么出现舍入误差的代价可能会很高,而这在 JavaScript 类型中是常态number
。
这有点像使用美元并使用 1234 美分作为存储类型,而不是 12,34 美元。
此外,Solidity 程序员喜欢将int256
类型作为默认类型,而无法将其 1:1 映射到 JavaScript 的number
。幸运的是,JavaScipt 不久前新增了一种名为 的数字类型BigInt
,它可以毫无问题地存储所有 Solidity 数字。
JavaScript
let x = 9999999999999999;
// will become 10,000,000,000,000,000
// because the number type can't store that big numbers reliably
let y = 9999999999999999n;
// will become 9,999,999,999,999,999
// because the n at the end tells JS that this is a BigInt and not a number
Solidity
int256 x = 9999999999999999;
合同与等级
Solidity 的合约与 JavaScript 的类类似,但又有所不同。这些合约正是 Solidity 应用程序被称为智能合约的原因。
Solidity 有点像 Java,因为合约是 Solidity 应用程序的入口点。合约看起来像 JavaScript 中的类,但区别在于实例的创建方式。
在 JavaScript 中,从类创建对象相对简单。只需使用new
关键字加上类名即可。
合约也可以这样做。new
在合约名称中使用关键字也会将新实例部署到区块链上。
JavaScript
class MyClass {
#value = 10;
setValue(x) {
this.#value = x;
}
}
Solidity
contract MyContract {
int256 private value = 10;
function setValue(int256 x) external {
value = x;
}
}
如你所见,this
在契约方法中是隐含的。因此,契约的属性在所有方法中始终处于作用域内。
合约实例、对象及其数据存在于区块链上,而不仅仅是在 Solidity 应用程序内存中。
当您将合约部署到以太坊区块链时,您实际上是在实例化该合约,然后您可以从其他合约或区块链客户端(如 Ethers.js)调用它。
合约会获得一个地址,稍后您可以使用该地址与其进行交互。如果您多次部署合约,则您将拥有多个地址来与不同的实例进行交互。
JavaScript
let x = new MyClass();
x.setValue(3);
Solidity
MyContract x = new MyContract(); // creates a new instance
x.setValue(3);
MyContract x = MyContract(contractAddress); // uses an existing instace
x.setValue();
在 JavaScript 中,如果关闭应用程序,则创建的对象就完成了;在 Solidity 中,合约实例在区块链上是持久的。
接口
您需要合约代码才能使用已部署的合约,但这些合约并非始终可用。因此,Solidity 还提供了接口,您可以在加载现有合约时定义并使用这些接口作为类型。
Solidity
interface MyInterface {
function setValue(int256 x) external;
}
...
MyInterface x = MyInterface(contractAddress); // uses an existing instace
x.setValue();
合约有许多标准化接口。例如,同质化代币和非同质化代币都是标准化的,这意味着我们可以查阅标准,复制所需的函数签名,并创建一个接口在合约中调用它们。像OpenZeppelin这样的项目也为我们提供了包含这些常用接口的库;我们无需自行创建。
用于包管理的 NPM
Solidity 使用我们已经从 JavaScript 中了解的 NPM 包管理器;这样,我们可以重用许多我们已经拥有的技能。
使用以下命令,我们将获得一个包含所有现有接口的库:
$ npm i @openzeppelin/contracts
全局变量和payable
每个函数中都有一些隐藏的全局变量。就像window
JavaScript 中的对象一样,Solidity 中也有一个msg
对象,其中包含函数调用者的数据。
下面是 JavaScript 中的一个示例,它将数据从全局window
对象加载到类的私有属性中。
JavaScript
class MyClass {
#title = null;
constructor() {
this.#title = window.document.title;
}
}
与 Solidity 相同,但这次,合约所有者将从全局变量中设置msg
。
Solidity
contract MyContract {
address paybale public owner;
constructor() payable {
owner = payable(msg.sender);
}
}
该msg
变量包含有关消息发送者的信息。在本例中,发送者是用于部署合约的地址。
constructor
当创建合约的新实例时,会自动调用此方法,只需使用 JavaScript 中类的新对象即可。由于需要有人创建该实例,因此他们的区块链地址最终会存储在msg.sender
变量中。
在示例中,所有这些函数和变量都定义为payable
,这意味着调用者可以向它们发送以太币。
这真是太棒了,因为它让我们能够在语言层面上为整个以太坊生态系统标准化的 Solidity 应用程序使用支付功能。JavaScript 中没有类似的功能;我们必须自己编写程序。
概括
Solidity 是一种简单的语言,其内置的支付机制可能是长期推动其发展的杀手级功能。
JavaScript 开发者应该非常熟悉大部分语法,并且少数存在的差异也能相对快速地掌握。此外,该生态系统还使用了 NPM,这对于 JavaScript 开发者来说更加有利。
本指南并非详尽无遗,仅涉及我所了解的一些基础知识。我并非 Solidity 的专家,因为我只使用了大约三个星期。
如果您对该方向的更多内容感兴趣,请告诉我!
另外,如果我有什么错误的话请告诉我:D
文章来源:https://dev.to/fllstck/solidity-basics-for-javascript-devs-57c