Tenderly Sandbox 是一个基于浏览器的智能合约快速迭代环境,它使用 Tenderly Forks 作为后端支持。该工具简化了智能合约的开发流程,允许开发者跳过繁琐的环境配置,直接编写、部署和运行代码。文章通过一个消息盒子的例子,展示了如何使用 Tenderly Sandbox 快速构建和调试智能合约,以及如何利用其提供的 Debugger 和事件监控功能。
隆重介绍 Tenderly Sandbox:这是一个基于浏览器的环境,用于快速迭代智能合约,由 Tenderly Forks 提供支持。 使用它可以立即部署和运行你的代码,缩短反馈时间,以便你可以快速行动,并轻松访问 Tenderly Debugger——Solidity 学习的必备工具。
学习一门编程语言需要你编写和使用代码,以了解不同的使用方式并理解它的特性。 学习 Solidity 也不例外。
但是,当刚开始学习 Web3 开发时,你需要处理许多技术问题,然后才能实际编写和运行你的智能合约。 从收集所有必要的工具到寻找值得信赖的区块链服务提供商,你需要花费大量时间和精力来设置你的环境,然后才能进入有趣的部分——在 Web3 中进行编码。
但是,如果你可以跳过冗长的设置过程并立即运行你的代码,而又不牺牲你的工作质量和学习体验,那会怎么样? 如果你可以将一切都为你准备好,以便你可以直接进入原型设计周期并专注于创造性部分,那会怎么样?
Tenderly Sandbox 允许你简化流程 并跳过耗时的任务,例如设置 MetaMask 帐户、连接到测试网络或处理任何本地依赖项。 它可以让你直接进入并开始试验 Solidity 智能合约。 这是一个由 Tenderly Forks 提供支持的强大、零设置、隔离的环境,将 Solidity 和 JavaScript 结合在一起。
在你学习和原型设计的开始阶段,你可能会经历一个典型的原型设计周期:设置你的环境 → 编写 → 部署 → 运行 → 检查结果 → 解决错误 → 重构和改进 → 部署 → 重复。
当然,你希望加快这个过程,并开始使用实际的 Solidity 代码,而不是进行环境设置的开发工作。 你还希望尽可能地灵活,这取决于较短的反馈时间:即进行更改与运行代码后获得结果之间的时间。
Sandbox 显著提高了原型设计周期的效率,因为你可以将更多精力放在创造性部分(编码)上,而不是技术细节上。 进入 Sandbox 后,你可以直接跳到编写,而部署和运行阶段会无缝且非常快速地发生。 反馈周期变短,从而可以更快地迭代你的代码。
而且,让我们面对现实吧,在你学习和原型设计你的智能合约时,你将会遇到失败和错误。 要解决这些问题,你可以直接进入 Tenderly Debugger 和其他功能,这些功能可以帮助你了解哪段代码失败了、为什么失败以及如何修复它。
一旦你弄清楚如何调整你的合约,你希望有一种快速的方法来重新运行它并确保它正常工作。 只需返回到你的 Sandbox 环境,进行任何必要的调整,然后重新运行 Sandbox 以验证你的解决方案。 这种即时部署和运行使你可以从一开始就了解你的合约如何执行并识别任何潜在的错误。
正如我们提到的,学习 Web3 编码的最好方法是实际去做。 那么,准备好开始工作了吗?
问题:消息框就像一个邮政信箱。 编写者可以为收件人地址存储一个整数值。 编写者可以为自己存储一个值。 如果存在,阅读者可以获取为其存储的值(基于其以太坊地址)。
第一个任务:找到一种同时为多个地址存储值的方法。 换句话说,你需要一个从 address 到 uint32 value 的 mapping,以及 set 和 get 方法。 让我们在第一次迭代中使用最简单的情况:set 存储发送者的消息,get 读取之前存储的消息。 然后我们将在第二次迭代中改进它。
这是智能合约的第一个草案:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.9.0;
contract MessageBox {
mapping(address => uint32) messages;
function set(uint32 val) public {
messages[msg.sender] = val;
}
function get() public view returns (uint) {
return messages[msg.sender];
}
}
让我们稍微探索一下这个合约:
messages
是一个映射,允许为不同的地址存储单个值(映射的 uint32
部分)。msg.sender
在 set
中是发送和签署交易的地址。 它用作存储给定值 val
的键。 本质上,发送者是在给自己留言。msg.sender
在 get
中允许访问存储在 storedValues
映射中的值。 实际上,get
的调用者会收到为其存储的消息。为了将其付诸实践,请前往 Sandbox 中的 Message Box Starter 示例。 在左侧,你将看到你的智能合约。 在右侧,你将看到一个最小的示例,演示如何设置和检索值。
接下来,单击 Run,你将在几秒钟内看到一系列事务。 这些事务是 JS 脚本发出的状态更改调用。
你的 Sandbox 视图应如下面的屏幕截图所示:
列表中的第一个事务是 Contract Creation 事务。 这个事务来自 await factory.deploy()
,它将合约的字节码“安装”到区块链上,使其可执行。 第二个事务调用 SimpleStorage
上的 set
方法。
你在此处看到的事务实际上已发送到 Tenderly Fork,后者充当网络并模拟事务执行。 每次你运行 Sandbox 时,都会部署一组新的合约并执行一组新的事务。 由于在 Fork 上执行,因此这些事务在区块浏览器上不可见。
到目前为止一切顺利,但让我们通过添加另一个功能来使事情变得有趣。
第二个任务: 使存储收件人的值成为可能。 可以将其视为给某人留言。 当收件人地址调用 get
时,他们应在此处获取存储的值。
为了实现这一点,让我们引入一个函数 setForAddress
,它接受收件人的地址和他们应该收到的值。
function setForAddress(address recipientAddress, uint32 val) public {
storedValues[recipientAddress] = val;
emit Stored(msg.sender, recipientAddress, val);
}
在这里,我们定义了一个 Solidity 事件 Stored
,该事件在调用 setForAddress
时发出。
为了使它更简洁,让我们在一个单独的内部函数中提取对 storedValues
的赋值。 这是完整的重构智能合约(暂时忽略 Stored 事件):
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.9.0;
contract MessageBox {
mapping(address => uint32) storedValues;
function set(uint32 val) public {
store(msg.sender, val);
}
function setForAddress(address recipientAddress, uint32 val) public {
store(recipientAddress, val);
}
function store(address recipientAddress, uint32 val) internal {
storedValues[recipientAddress] = val;
emit Stored(msg.sender, recipientAddress, val);
}
function get() public view returns (uint) {
return storedValues[msg.sender];
}
event Stored(address from, address to, uint32 val);
}
event Stored(address from, address to, uint32 val);
}
再次,单击 Run 按钮,Sandbox 代码执行的事务列表将很快显示。 单击 Transaction 部分中的 Expand 按钮以获取事务的全屏视图。 在这里,你将看到两个调用:set
和 setForAddress
。
单击第二个事务(setForAddress
),这将带你到 Tenderly Dashboard。 接下来,单击 View input data 按钮以获取更多信息。 这样,你可以查看与事务一起发送的确切参数。
这是你的视图应如下所示:
当你位于 Tenderly Dashboard 中时,你可以收集有关已执行事务的其他重要信息:
State Changes(状态变更):要了解你的代码如何影响区块链的状态,请打开 State Changes 标签。 你应该看到类似于以下屏幕截图的内容。 它表明 storedValues
存储变量已被修改。 密钥 0x3dfeb36487c8b5839a0a2ab65ce4e55dbea753fa
下的条目等于设置的值 – 42。
Events(事件):存储的第二次迭代包括发送一个 Stored
事件,该事件捕获值(val
)、存储值的地址(from
)以及值的预期地址(to
)。 如果你单击 Events 标签,你将看到此确切信息:
要访问 JavaScript 代码中的事件,请将其添加到 Sandbox 的 JS 部分的底部并观察输出:
const setFourTx = await simpleStorage.setForAddress(RECIPIENT_ADDRESS, 4);
// 等待事务收据 - 它包含事件
const setFourReceipt = await setFourTx.wait();
// 找到第一个(也是唯一一个)Stored 事件
const storedEvent = setFourReceipt.events.filter(e => e.event == 'Stored')[0];
// 将 storedEvents.args 视为一个元组,其组件
// 由事件定义
const [addressFrom, addressTo, value] = storedEvent.args;
console.log(`Address ${addressFrom} stored value ${value} for ${addressTo} to read`);
在此示例中,我们决定不存储有关存储值的发送者的信息,因为它对智能合约的执行没有影响。 我们的确发出了一个 Stored
事件。 你可以将其视为一个元组 (from, to, value)
。 这使我们可以在不将数据存储在智能合约状态中的情况下,使用其他信息来补充状态更改。
事件是保留导致状态更改的主要事件日志的有用方法。 事件日志是对智能合约状态更改的补充信息。 你可以使用 Ethers 订阅这些事件 在你的客户端应用程序中,以便你尽快了解它们。 或者,你可以探索如何设置 Tenderly Web3 Action 以跟踪链上事件 并为你的智能合约构建无服务器 Web3 后端。
Tenderly Sandbox 是一个很好的选择,可以在学习 Solidity 时进行实验,并探索该语言的不同概念如何协同工作。 作为一个已经设置好的环境,它可以让你将原型设计周期的大部分时间用于编写代码和寻找创造性的解决方案。 此外,由于其他 Tenderly 工具只需单击一下即可获得,因此你可以轻松获取你需要的有价值的信息。
但是,学习和发现此环境所能提供的最佳方法是通过实践。 那么,为什么不尝试使用 Sandbox 编写一个投票智能合约 或查看这个创建子货币合约的示例? 从等式中消除干扰,并将注意力集中在实际的 Solidity 编码上。
- 原文链接: blog.tenderly.co/how-to-...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!