Package: titanoboa
TitanoboaAVyperinterpreter with pretty tracebacks, forking, debugging features and more! Titanoboa's goal is to provide a modern, advanced and integrated development experience for vyper users.ArchitectureTitanoboa achieves feature parity with the vyper compiler while providing an interpreted experience. How does it do this? Internally, titanoboa uses vyper as a library to compile source code to bytecode, and then runs the bytecode usingpy-evm, adding instrumenting hooks to provide introspection. The use ofpy-evmmeans that the entire experience is highly configurable, down to the ability to patch opcodes and precompiles at the EVM level.DocumentationUsage and quickstart arebelow. For more detailed documentation, please see thedocumentation.Installationpip install titanoboaFor latest dev version:pip install git+https://github.com/vyperlang/titanoboaIf you are installing titanoboa from git alongside brownie, you may have to manually install titanoboaafterinstalling browniepip install brownie
pip install git+https://github.com/vyperlang/titanoboaSometimes, usingpypycan result in a substantial performance improvement for computation heavy contracts.Pypycan usually be used as a drop-in replacement forCPython.To get a performance boost for mainnet forking, install with theforking-recommendedextra (pip install "git+https://github.com/vyperlang/titanoboa#egg=titanoboa[forking-recommended]", orpip install titanoboa[forking-recommended]). This installsplyvelto cache RPC results between sessions, andujsonwhich improves json performance.If you are running titanoboa on a localVyperproject folder, you might need to runpython setup.py installon yourVyperproject if you encounter errors such asModuleNotFoundError: No module named 'vyper.version'BackgroundTitanoboa (/ˌtaɪtənəˈboʊə/;[1] lit. 'titanic boa') is an extinct genus of very large snakes that lived in what is now La Guajira in northeastern Colombia. They could grow up to 12.8 m (42 ft), perhaps even 14.3 m (47 ft) long and reach a body mass of 730–1,135 kg (1,610–2,500 lb). This snake lived during the Middle to Late Paleocene epoch, around 60 to 58 million years ago, following the extinction of all non-avian dinosaurs. Although originally thought to be an apex predator, the discovery of skull bones revealed that it was more than likely specialized in preying on fish. The only known species is Titanoboa cerrejonensis, the largest snake ever discovered,[2] which supplanted the previous record holder, Gigantophis garstini.[3]Usage / Quick StartHello, worldimportboaboa.eval("empty(uint256)")Basic# simple.vy
@external
def foo() -> uint256:
    x: uint256 = 1
    return x + 7>>>importboa>>>simple=boa.load("examples/simple.vy")>>>simple.foo()8>>>simple.foo()._vyper_typeuint256Passing__init__>>>importboa>>>erc20=boa.load("examples/ERC20.vy",'titanoboa','boa',18,1)>>>erc20.name()titanoboa>>>erc20.symbol()boa>>>erc20.balanceOf(erc20.address)0>>>erc20.totalSupply()1000000000000000000As a blueprint>>>importboa>>>s=boa.load_partial("examples/ERC20.vy")>>>blueprint=s.deploy_as_blueprint()>>>deployer=boa.load("examples/deployer.vy",blueprint)>>>token=s.at(deployer.create_new_erc20("token","TKN",18,10**18))>>>token.totalSupply()>>>1000000000000000000000000000000000000Expecting BoaErrors / handling reverts>>>importboa>>>erc20=boa.load("examples/ERC20.vy","titanoboa","boa",18,0)>>>withboa.env.prank(boa.env.generate_address()):...withboa.reverts():...erc20.mint(boa.env.eoa,100)# non-minter cannot mint...>>>withboa.env.prank(boa.env.generate_address()):...# you can be more specific about the failure reason...withboa.reverts(rekt="non-minter tried to mint"):...erc20.mint(boa.env.eoa,100)From within IPythonIn[1]:%load_extboa.ipythonimportboaboa.interpret.set_cache_dir()# cache source compilations across sessionsIn[2]:%vypermsg.sender# evaluate a vyper expression directlyOut[2]:'0x0000000000000000000000000000000000000065'In[3]:%%vyper...:...:MY_IMMUTABLE:immutable(uint256)...:...:@external...:def__init__(some_number:uint256):...:MY_IMMUTABLE=some_number*2...:...:@external...:deffoo()->uint256:...:returnMY_IMMUTABLE...:Out[3]:<boa.vyper.contract.VyperDeployerat0x7f3496187190>In[4]:d=_In[4]:c=d.deploy(5)In[5]:c.foo()Out[5]:10Evaluating arbitrary code>>>erc20=boa.load("examples/ERC20.vy",'titanoboa','boa',18,1)>>>erc20.balanceOf(erc20.address)0>>>erc20.totalSupply()1000000000000000000>>>erc20.eval("self.totalSupply += 10")# manually mess with total supply>>>erc20.totalSupply()1000000000000000010>>>erc20.eval("self.totalSupply")# same result when eval'ed1000000000000000010>>>erc20.eval("self.balanceOf[msg.sender] += 101")# manually mess with balance>>>erc20.balanceOf(boa.env.eoa)1000000000000000101>>>erc20.eval("self.balanceOf[msg.sender]")# same result when eval'ed1000000000000000101Note that ineval()mode, titanoboa uses slightly different optimization settings, so gas usage may not be the same as using the external interface.ForkingCreate a fork of mainnet given rpc.In[1]:importboa;boa.env.fork(url="<rpc server address>")In[2]:%load_extboa.ipythonIn[3]:%%vyperTest...:interfaceHasName:...:defname()->String[32]:view...:...:@external...:defget_name_of(addr:HasName)->String[32]:...:returnaddr.name()Out[3]:<boa.vyper.contract.VyperDeployerat0x7f3496187190>In[4]:c=Test.deploy()In[5]:c.get_name_of("0xD533a949740bb3306d119CC777fa900bA034cd52")Out[5]:'Curve DAO Token'Cast current deployed addresses to vyper contract>>>importboa;boa.env.fork(url="<rpc server address>")>>>c=boa.load_partial("examples/ERC20.vy").at("0xD533a949740bb3306d119CC777fa900bA034cd52")>>>c.name()'Curve DAO Token'Network Mode>>>importboa;fromboa.networkimportNetworkEnv>>>frometh_accountimportAccount>>>boa.env.set_env(NetworkEnv("<rpc server address>"))>>># in a real codebase, always load private keys safely from an encrypted store!>>>boa.env.add_account(Account(<aprivatekey>))>>>c=boa.load("examples/ERC20.vy","My Token","TKN",10**18,10)>>>c.name()'My Token'Jupyter IntegrationYou can use Jupyter to execute titanoboa code in network mode from your browser using any wallet, usingboa.integrations.jupyter.BrowserSigneras a drop-in replacement foreth_account.Account. For a full example, please seethis example Jupyter notebookBasic tests$python-mtests.integration.sim_veYFI