diff --git a/.circleci/config.yml b/.circleci/config.yml index fa5b396a34f..2aaa0121d5b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -14,12 +14,13 @@ jobs: - checkout - run: name: multi_os_result - command: curl http://60.205.215.34/multi_os_result + command: echo "curl http://60.205.215.34/multi_os_result" +# +# - run: +# name: Daily Build Report +# command: curl http://60.205.215.34/Daily_Build_Task_Report +# +# - run: +# name: Download Links +# command: sh DownloadLinks.sh - - run: - name: Daily Build Report - command: curl http://60.205.215.34/Daily_Build_Task_Report - - - run: - name: Download Links - command: sh DownloadLinks.sh diff --git a/README.md b/README.md index ec1e80146f2..486d301281a 100644 --- a/README.md +++ b/README.md @@ -42,319 +42,61 @@

- How to Build • - How to Run • - Links • + Quick Start • + Deploy • + Developer CommunityDocumentation • - Contributing • - Community + Contributing • + Projects • + Resource

## What's TRON? -TRON is a project dedicated to building the infrastructure for a truly decentralized Internet. +TRON is a project dedicated to building the infrastructure for a truly decentralized Internet. -The Tron Protocol, one of the largest blockchain based operating systems in the world, offers scalable, high-availability and high-throughput support that underlies all the decentralized applications in the TRON ecosystem. -TRON enables large-scale development and engagement. With over 2000 transactions per second (TPS), high concurrency, low latency and massive data transmission, TRON is ideal for building decentralized entertainment applications. Free features and incentive systems allow developers to create premium app experiences for users. +* Tron Protocol, one of the largest blockchain based operating systems in the world, offers scalable, high-availability and high-throughput support that underlies all the decentralized applications in the TRON ecosystem. -TRON Protocol and the Tron Virtual Machine (TVM) allow anyone to develop decentralized applications (DAPPs) for themselves or their communities with smart contracts thereby making decentralized crowdfunding and token issuance easier than ever. +* Tron Virtual Machine (TVM) allow anyone to develop decentralized applications (DAPPs) for themselves or their communities with smart contracts thereby making decentralized crowdfunding and token issuance easier than ever. -# How to Build - -## Prepare dependencies - -* JDK 1.8 (JDK 1.9+ are not supported yet) -* On Linux Ubuntu system (e.g. Ubuntu 16.04.4 LTS), ensure that the machine has [__Oracle JDK 8__](https://www.digitalocean.com/community/tutorials/how-to-install-java-with-apt-get-on-ubuntu-16-04), instead of having __Open JDK 8__ in the system. If you are building the source code by using __Open JDK 8__, you will get [__Build Failed__](https://github.com/tronprotocol/java-tron/issues/337) result. -* Open **UDP** ports for connection to the network -* **MINIMUM** 2 ENERGY Cores - -## Build and Deploy automatically using scripts - -- Please take a look at the [Tron Deployment Scripts](https://github.com/tronprotocol/TronDeployment) repository. - -## Getting the code with git - -* Use Git from the Terminal, see the [Setting up Git](https://help.github.com/articles/set-up-git/) and [Fork a Repo](https://help.github.com/articles/fork-a-repo/) articles. -* develop branch: the newest code -* master branch: more stable than develop. -In the shell command, type: -```bash -git clone https://github.com/tronprotocol/java-tron.git -git checkout -t origin/master -``` - -* For Mac, you can also install **[GitHub for Mac](https://mac.github.com/)** then **[fork and clone our repository](https://guides.github.com/activities/forking/)**. - -* If you'd rather not use Git, [Download the ZIP](https://github.com/tronprotocol/java-tron/archive/develop.zip) - -## Including java-tron as dependency - -* If you don't want to checkout the code and build the project, you can include it directly as a dependency - -**Using gradle:** - -``` -repositories { - maven { url 'https://jitpack.io' } -} -dependencies { - implementation 'com.github.tronprotocol:java-tron:develop-SNAPSHOT' -} -``` - -**Using maven:** - -```xml -... - - - jitpack.io - https://jitpack.io - - -... - - com.github.tronprotocol - java-tron - develop-SNAPSHOT - -``` - - - - -## Building from source code - -* Build in the Terminal - -```bash -cd java-tron -./gradlew build -``` - - -* Build in [IntelliJ IDEA](https://www.jetbrains.com/idea/) (community version is enough): - - **Please run ./gradlew build once to build the protocol files** - - 1. Start IntelliJ. Select `File` -> `Open`, then locate to the java-tron folder which you have git cloned to your local drive. Then click `Open` button on the right bottom. - 2. Check on `Use auto-import` on the `Import Project from Gradle` dialog. Select JDK 1.8 in the `Gradle JVM` option. Then click `OK`. - 3. IntelliJ will open the project and start gradle syncing, which will take several minutes, depending on your network connection and your IntelliJ configuration - 4. Enable Annotations, `Preferences` -> Search `annotations` -> check `Enable Annotation Processing`. - 5. After the syncing finished, select `Gradle` -> `Tasks` -> `build`, and then double click `build` option. - -# Running - -### Running multi-nodes - -https://github.com/tronprotocol/Documentation/blob/master/TRX/Solidity_and_Full_Node_Deployment_EN.md - -## Running a local node and connecting to the public testnet - -* Use the [Testnet Config](https://github.com/tronprotocol/TronDeployment/blob/master/test_net_config.conf) or use the [Tron Deployment Scripts](https://github.com/tronprotocol/TronDeployment) - - -### Running a Super Representative Node for mainnet - -* Use the executable JAR(Recommended way) - -```bash -java -jar FullNode.jar -p your private key --witness -c your config.conf(Example:/data/java-tron/config.conf) -Example: -java -jar FullNode.jar -p 650950B193DDDDB35B6E48912DD28F7AB0E7140C1BFDEFD493348F02295BD812 --witness -c /data/java-tron/config.conf - -``` - -This is similar to running a private testnet, except that the IPs in the `config.conf` are officially declared by TRON. - -
-Correct output - -```bash - -20:43:18.138 INFO [main] [o.t.p.FullNode](FullNode.java:21) Full node running. -20:43:18.486 INFO [main] [o.t.c.c.a.Args](Args.java:429) Bind address wasn't set, Punching to identify it... -20:43:18.493 INFO [main] [o.t.c.c.a.Args](Args.java:433) UDP local bound to: 10.0.8.146 -20:43:18.495 INFO [main] [o.t.c.c.a.Args](Args.java:448) External IP wasn't set, using checkip.amazonaws.com to identify it... -20:43:19.450 INFO [main] [o.t.c.c.a.Args](Args.java:461) External address identified: 47.74.147.87 -20:43:19.599 INFO [main] [o.s.c.a.AnnotationConfigApplicationContext](AbstractApplicationContext.java:573) Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@124c278f: startup date [Fri Apr 27 20:43:19 CST 2018]; root of context hierarchy -20:43:19.972 INFO [main] [o.s.b.f.a.AutowiredAnnotationBeanPostProcessor](AutowiredAnnotationBeanPostProcessor.java:153) JSR-330 'javax.inject.Inject' annotation found and supported for autowiring -20:43:20.380 INFO [main] [o.t.c.d.DynamicPropertiesStore](DynamicPropertiesStore.java:244) update latest block header timestamp = 0 -20:43:20.383 INFO [main] [o.t.c.d.DynamicPropertiesStore](DynamicPropertiesStore.java:252) update latest block header number = 0 -20:43:20.393 INFO [main] [o.t.c.d.DynamicPropertiesStore](DynamicPropertiesStore.java:260) update latest block header id = 00 -20:43:20.394 INFO [main] [o.t.c.d.DynamicPropertiesStore](DynamicPropertiesStore.java:265) update state flag = 0 -20:43:20.559 INFO [main] [o.t.c.c.TransactionCapsule](TransactionCapsule.java:83) Transaction create succeeded! -20:43:20.567 INFO [main] [o.t.c.c.TransactionCapsule](TransactionCapsule.java:83) Transaction create succeeded! -20:43:20.568 INFO [main] [o.t.c.c.TransactionCapsule](TransactionCapsule.java:83) Transaction create succeeded! -20:43:20.568 INFO [main] [o.t.c.c.TransactionCapsule](TransactionCapsule.java:83) Transaction create succeeded! -20:43:20.569 INFO [main] [o.t.c.c.TransactionCapsule](TransactionCapsule.java:83) Transaction create succeeded! -20:43:20.596 INFO [main] [o.t.c.d.Manager](Manager.java:300) create genesis block -20:43:20.607 INFO [main] [o.t.c.d.Manager](Manager.java:306) save block: BlockCapsule - -``` - -Then observe whether block synchronization success,If synchronization successfully explains the success of the super node - -
- - -### Running a Super Representative Node for private testnet -* use master branch -* You should modify the config.conf - 1. Replace existing entry in genesis.block.witnesses with your address. - 2. Replace existing entry in seed.node ip.list with your ip list. - 3. The first Super Node start, needSyncCheck should be set false - 4. Set p2pversion to 61 - -* Use the executable JAR(Recommended way) - -```bash -cd build/libs -java -jar FullNode.jar -p your private key --witness -c your config.conf (Example:/data/java-tron/config.conf) -Example: -java -jar FullNode.jar -p 650950B193DDDDB35B6E48912DD28F7AB0E7140C1BFDEFD493348F02295BD812 --witness -c /data/java-tron/config.conf - -``` - -
-Show Output - -```bash -> ./gradlew run -Pwitness - -> Task :generateProto UP-TO-DATE -Using TaskInputs.file() with something that doesn't resolve to a File object has been deprecated and is scheduled to be removed in Gradle 5.0. Use TaskInputs.files() instead. - -> Task :run -20:39:22.749 INFO [o.t.c.c.a.Args] private.key = 63e62a71ed39e30bac7223097a173924aad5855959de517ff2987b0e0ec89f1a -20:39:22.816 WARN [o.t.c.c.a.Args] localwitness size must be one, get the first one -20:39:22.832 INFO [o.t.p.FullNode] Here is the help message.output-directory/ -三月 22, 2018 8:39:23 下午 org.tron.core.services.RpcApiService start -信息: Server started, listening on 50051 -20:39:23.706 INFO [o.t.c.o.n.GossipLocalNode] listener message -20:39:23.712 INFO [o.t.c.o.n.GossipLocalNode] sync group = a41d27f10194c53703be90c6f8735bb66ffc53aa10ea9024d92dbe7324b1aee3 -20:39:23.716 INFO [o.t.c.s.WitnessService] Sleep : 1296 ms,next time:2018-03-22T20:39:25.000+08:00 -20:39:23.734 WARN [i.s.t.BootstrapFactory] Env doesn't support epoll transport -20:39:23.746 INFO [i.s.t.TransportImpl] Bound to: 192.168.10.163:7080 -20:39:23.803 INFO [o.t.c.n.n.NodeImpl] other peer is nil, please wait ... -20:39:25.019 WARN [o.t.c.d.Manager] nextFirstSlotTime:[2018-03-22T17:57:20.001+08:00],now[2018-03-22T20:39:25.067+08:00] -20:39:25.019 INFO [o.t.c.s.WitnessService] ScheduledWitness[448d53b2df0cd78158f6f0aecdf60c1c10b15413],slot[1946] -20:39:25.021 INFO [o.t.c.s.WitnessService] It's not my turn -20:39:25.021 INFO [o.t.c.s.WitnessService] Sleep : 4979 ms,next time:2018-03-22T20:39:30.000+08:00 -20:39:30.003 WARN [o.t.c.d.Manager] nextFirstSlotTime:[2018-03-22T17:57:20.001+08:00],now[2018-03-22T20:39:30.052+08:00] -20:39:30.003 INFO [o.t.c.s.WitnessService] ScheduledWitness[6c22c1af7bfbb2b0e07148ecba27b56f81a54fcf],slot[1947] -20:39:30.003 INFO [o.t.c.s.WitnessService] It's not my turn -20:39:30.003 INFO [o.t.c.s.WitnessService] Sleep : 4997 ms,next time:2018-03-22T20:39:35.000+08:00 -20:39:33.803 INFO [o.t.c.n.n.NodeImpl] other peer is nil, please wait ... -20:39:35.005 WARN [o.t.c.d.Manager] nextFirstSlotTime:[2018-03-22T17:57:20.001+08:00],now[2018-03-22T20:39:35.054+08:00] -20:39:35.005 INFO [o.t.c.s.WitnessService] ScheduledWitness[48e447ec869216de76cfeeadf0db37a3d1c8246d],slot[1948] -20:39:35.005 INFO [o.t.c.s.WitnessService] It's not my turn -20:39:35.005 INFO [o.t.c.s.WitnessService] Sleep : 4995 ms,next time:2018-03-22T20:39:40.000+08:00 -20:39:40.005 WARN [o.t.c.d.Manager] nextFirstSlotTime:[2018-03-22T17:57:20.001+08:00],now[2018-03-22T20:39:40.055+08:00] -20:39:40.010 INFO [o.t.c.d.Manager] postponedTrxCount[0],TrxLeft[0] -20:39:40.022 INFO [o.t.c.d.DynamicPropertiesStore] update latest block header id = fd30a16160715f3ca1a5bcad18e81991cd6f47265a71815bd2c943129b258cd2 -20:39:40.022 INFO [o.t.c.d.TronStoreWithRevoking] Address is [108, 97, 116, 101, 115, 116, 95, 98, 108, 111, 99, 107, 95, 104, 101, 97, 100, 101, 114, 95, 104, 97, 115, 104], BytesCapsule is org.tron.core.capsule.BytesCapsule@2ce0e954 -20:39:40.023 INFO [o.t.c.d.DynamicPropertiesStore] update latest block header number = 140 -20:39:40.024 INFO [o.t.c.d.TronStoreWithRevoking] Address is [108, 97, 116, 101, 115, 116, 95, 98, 108, 111, 99, 107, 95, 104, 101, 97, 100, 101, 114, 95, 110, 117, 109, 98, 101, 114], BytesCapsule is org.tron.core.capsule.BytesCapsule@83924ab -20:39:40.024 INFO [o.t.c.d.DynamicPropertiesStore] update latest block header timestamp = 1521722380001 -20:39:40.024 INFO [o.t.c.d.TronStoreWithRevoking] Address is [108, 97, 116, 101, 115, 116, 95, 98, 108, 111, 99, 107, 95, 104, 101, 97, 100, 101, 114, 95, 116, 105, 109, 101, 115, 116, 97, 109, 112], BytesCapsule is org.tron.core.capsule.BytesCapsule@ca6a6f8 -20:39:40.024 INFO [o.t.c.d.Manager] updateWitnessSchedule number:140,HeadBlockTimeStamp:1521722380001 -20:39:40.025 WARN [o.t.c.u.RandomGenerator] index[-3] is out of range[0,3],skip -20:39:40.070 INFO [o.t.c.d.TronStoreWithRevoking] Address is [73, 72, -62, -24, -89, 86, -39, 67, 112, 55, -36, -40, -57, -32, -57, 61, 86, 12, -93, -115], AccountCapsule is account_name: "Sun" -address: "IH\302\350\247V\331Cp7\334\330\307\340\307=V\f\243\215" -balance: 9223372036854775387 - -20:39:40.081 INFO [o.t.c.d.TronStoreWithRevoking] Address is [41, -97, 61, -72, 10, 36, -78, 10, 37, 75, -119, -50, 99, -99, 89, 19, 47, 21, 127, 19], AccountCapsule is type: AssetIssue -address: ")\237=\270\n$\262\n%K\211\316c\235Y\023/\025\177\023" -balance: 420 - -20:39:40.082 INFO [o.t.c.d.TronStoreWithRevoking] Address is [76, 65, 84, 69, 83, 84, 95, 83, 79, 76, 73, 68, 73, 70, 73, 69, 68, 95, 66, 76, 79, 67, 75, 95, 78, 85, 77], BytesCapsule is org.tron.core.capsule.BytesCapsule@ec1439 -20:39:40.083 INFO [o.t.c.d.Manager] there is account List size is 8 -20:39:40.084 INFO [o.t.c.d.Manager] there is account ,account address is 448d53b2df0cd78158f6f0aecdf60c1c10b15413 -20:39:40.084 INFO [o.t.c.d.Manager] there is account ,account address is 548794500882809695a8a687866e76d4271a146a -20:39:40.084 INFO [o.t.c.d.Manager] there is account ,account address is 48e447ec869216de76cfeeadf0db37a3d1c8246d -20:39:40.084 INFO [o.t.c.d.Manager] there is account ,account address is 55ddae14564f82d5b94c7a131b5fcfd31ad6515a -20:39:40.085 INFO [o.t.c.d.Manager] there is account ,account address is 6c22c1af7bfbb2b0e07148ecba27b56f81a54fcf -20:39:40.085 INFO [o.t.c.d.Manager] there is account ,account address is 299f3db80a24b20a254b89ce639d59132f157f13 -20:39:40.085 INFO [o.t.c.d.Manager] there is account ,account address is abd4b9367799eaa3197fecb144eb71de1e049150 -20:39:40.085 INFO [o.t.c.d.Manager] there is account ,account address is 4948c2e8a756d9437037dcd8c7e0c73d560ca38d -20:39:40.085 INFO [o.t.c.d.TronStoreWithRevoking] Address is [108, 34, -63, -81, 123, -5, -78, -80, -32, 113, 72, -20, -70, 39, -75, 111, -127, -91, 79, -49], WitnessCapsule is org.tron.core.capsule.WitnessCapsule@4cb4f7fb -20:39:40.086 INFO [o.t.c.d.TronStoreWithRevoking] Address is [41, -97, 61, -72, 10, 36, -78, 10, 37, 75, -119, -50, 99, -99, 89, 19, 47, 21, 127, 19], WitnessCapsule is org.tron.core.capsule.WitnessCapsule@7be2474a -20:39:40.086 INFO [o.t.c.d.TronStoreWithRevoking] Address is [72, -28, 71, -20, -122, -110, 22, -34, 118, -49, -18, -83, -16, -37, 55, -93, -47, -56, 36, 109], WitnessCapsule is org.tron.core.capsule.WitnessCapsule@3e375891 -20:39:40.086 INFO [o.t.c.d.TronStoreWithRevoking] Address is [68, -115, 83, -78, -33, 12, -41, -127, 88, -10, -16, -82, -51, -10, 12, 28, 16, -79, 84, 19], WitnessCapsule is org.tron.core.capsule.WitnessCapsule@55d77b83 -20:39:40.090 INFO [o.t.c.d.Manager] countWitnessMap size is 0 -20:39:40.091 INFO [o.t.c.d.TronStoreWithRevoking] Address is [41, -97, 61, -72, 10, 36, -78, 10, 37, 75, -119, -50, 99, -99, 89, 19, 47, 21, 127, 19], WitnessCapsule is org.tron.core.capsule.WitnessCapsule@310dd876 -20:39:40.092 INFO [o.t.c.d.TronStoreWithRevoking] Address is [72, -28, 71, -20, -122, -110, 22, -34, 118, -49, -18, -83, -16, -37, 55, -93, -47, -56, 36, 109], WitnessCapsule is org.tron.core.capsule.WitnessCapsule@151b42bc -20:39:40.092 INFO [o.t.c.d.TronStoreWithRevoking] Address is [108, 34, -63, -81, 123, -5, -78, -80, -32, 113, 72, -20, -70, 39, -75, 111, -127, -91, 79, -49], WitnessCapsule is org.tron.core.capsule.WitnessCapsule@2d0388aa -20:39:40.092 INFO [o.t.c.d.TronStoreWithRevoking] Address is [68, -115, 83, -78, -33, 12, -41, -127, 88, -10, -16, -82, -51, -10, 12, 28, 16, -79, 84, 19], WitnessCapsule is org.tron.core.capsule.WitnessCapsule@478a55e7 -20:39:40.101 INFO [o.t.c.d.TronStoreWithRevoking] Address is [-3, 48, -95, 97, 96, 113, 95, 60, -95, -91, -68, -83, 24, -24, 25, -111, -51, 111, 71, 38, 90, 113, -127, 91, -46, -55, 67, 18, -101, 37, -116, -46], BlockCapsule is BlockCapsule{blockId=fd30a16160715f3ca1a5bcad18e81991cd6f47265a71815bd2c943129b258cd2, num=140, parentId=dadeff07c32d342b941cfa97ba82870958615e7ae73fffeaf3c6a334d81fe3bd, generatedByMyself=true} -20:39:40.102 INFO [o.t.c.d.Manager] save block: BlockCapsule{blockId=fd30a16160715f3ca1a5bcad18e81991cd6f47265a71815bd2c943129b258cd2, num=140, parentId=dadeff07c32d342b941cfa97ba82870958615e7ae73fffeaf3c6a334d81fe3bd, generatedByMyself=true} -20:39:40.102 INFO [o.t.c.s.WitnessService] Block is generated successfully, Its Id is fd30a16160715f3ca1a5bcad18e81991cd6f47265a71815bd2c943129b258cd2,number140 -20:39:40.102 INFO [o.t.c.n.n.NodeImpl] Ready to broadcast a block, Its hash is fd30a16160715f3ca1a5bcad18e81991cd6f47265a71815bd2c943129b258cd2 -20:39:40.107 INFO [o.t.c.s.WitnessService] Produced -20:39:40.107 INFO [o.t.c.s.WitnessService] Sleep : 4893 ms,next time:2018-03-22T20:39:45.000+08:00 -20:39:43.805 INFO [o.t.c.n.n.NodeImpl] other peer is nil, please wait ... -20:39:45.002 WARN [o.t.c.d.Manager] nextFirstSlotTime:[2018-03-22T20:39:45.001+08:00],now[2018-03-22T20:39:45.052+08:00] -20:39:45.003 INFO [o.t.c.s.WitnessService] ScheduledWitness[48e447ec869216de76cfeeadf0db37a3d1c8246d],slot[1] -20:39:45.003 INFO [o.t.c.s.WitnessService] It's not my turn -20:39:45.003 INFO [o.t.c.s.WitnessService] Sleep : 4997 ms,next time:2018-03-22T20:39:50.000+08:00 -20:39:50.002 WARN [o.t.c.d.Manager] nextFirstSlotTime:[2018-03-22T20:39:45.001+08:00],now[2018-03-22T20:39:50.052+08:00] -20:39:50.003 INFO [o.t.c.s.WitnessService] ScheduledWitness[6c22c1af7bfbb2b0e07148ecba27b56f81a54fcf],slot[2] -20:39:50.003 INFO [o.t.c.s.WitnessService] It's not my turn -20:39:50.003 INFO [o.t.c.s.WitnessService] Sleep : 4997 ms,next time:2018-03-22T20:39:55.000+08:00 - -``` - -
- -* In IntelliJ IDEA - -
- - -Open the configuration panel: - - - -![](docs/images/program_configure.png) - -
- -
- - -In the `Program arguments` option, fill in `--witness`: - - - -![](docs/images/set_witness_param.jpeg) - -
- -Then, run `FullNode::main()` again. +TRON enables large-scale development and engagement. With over 2000 transactions per second (TPS), high concurrency, low latency and massive data transmission. It is ideal for building decentralized entertainment applications. Free features and incentive systems allow developers to create premium app experiences for users. # Quick Start -Read the [Quick Start](https://developers.tron.network/docs/getting-started-1). +* [Quick Start](./quickstart.md) TRON Quickstart image setup -# Advanced Configurations - -Read the [Advanced Configurations](src/main/java/org/tron/core/config/README.md). +# Deploy +* [Build](./build.md) Please build java-tron after cloning the project +* [Run](./run.md) Run java-tron # Developer Community * [Discord](https://discord.gg/GsRgsTD) Please join our Developer Discord * [Gitter](https://gitter.im/tronprotocol/allcoredev) the core dev gitter -# Links - -* [Website](https://tron.network/) -* [Documentation](http://developers.tron.network) -* [Blog](https://tronprotocol.github.io/tron-blog/) - # Projects - * [TRON Protocol](https://github.com/tronprotocol/protocol) * [Wallet Client](https://github.com/tronprotocol/wallet-cli) * [Wallet Web](https://github.com/tronprotocol/wallet-web) + +# Resource +* [Website](https://tron.network/) +* [Documentation](http://developers.tron.network) +* [Blog](https://tronprotocol.github.io/tron-blog/) +* [Tronscan](https://tronscan.org/) +* [Trxplorer](https://www.trxplorer.io/) +* [White Paper](https://tron.network/resources?lng=&name=1) +* [TRON Quickstart](https://developers.tron.network/docs/getting-started-1) +* [About](https://tron.network/about) +* [FAQ](https://tron.network/faq) + +# Contributing +Thank you for all of [our contributors](https://github.com/tronprotocol/java-tron/graphs/contributors); this project wouldn’t be what it is without you! If you want to help out, please see [CONTRIBUTING.md](CONTRIBUTING.md). + +If you'd like to contribute to java-tron, please fork, fix, commit and send a pull request for the maintainers to review and merge into the main code base. +If you wish to submit more complex changes though, please check up with the core devs first on [our gitter channel](https://gitter.im/tronprotocol/allcoredev) to ensure those changes are +in line with the general philosophy of the project and/or get some early feedback which can make both your efforts much lighter as well as our review and merge procedures quick and simple. + +# License +* [MIT](https://github.com/tronprotocol/java-tron/blob/master/LICENSE) diff --git a/build.gradle b/build.gradle index eaea8f731ee..6464ec87001 100755 --- a/build.gradle +++ b/build.gradle @@ -180,6 +180,8 @@ dependencies { compile "io.vavr:vavr:0.9.2" compile group: 'org.pf4j', name: 'pf4j', version: '2.5.0' + compile group: 'org.zeromq', name: 'jeromq', version: '0.5.0' + } check.dependsOn 'lint' diff --git a/build.md b/build.md new file mode 100644 index 00000000000..465f53da52f --- /dev/null +++ b/build.md @@ -0,0 +1,84 @@ +# How to Build + +## Prepare dependencies + +* JDK 1.8 (JDK 1.9+ are not supported yet) +* On Linux Ubuntu system (e.g. Ubuntu 16.04.4 LTS), ensure that the machine has [__Oracle JDK 8__](https://www.digitalocean.com/community/tutorials/how-to-install-java-with-apt-get-on-ubuntu-16-04), instead of having __Open JDK 8__ in the system. If you are building the source code by using __Open JDK 8__, you will get [__Build Failed__](https://github.com/tronprotocol/java-tron/issues/337) result. +* Open **UDP** ports for connection to the network +* **MINIMUM** 2 ENERGY Cores + +## Build and Deploy automatically using scripts + +- Please take a look at the [Tron Deployment Scripts](https://github.com/tronprotocol/TronDeployment) repository. + +## Getting the code with git + +* Use Git from the Terminal, see the [Setting up Git](https://help.github.com/articles/set-up-git/) and [Fork a Repo](https://help.github.com/articles/fork-a-repo/) articles. +* develop branch: the newest code +* master branch: more stable than develop. +In the shell command, type: +```bash +git clone https://github.com/tronprotocol/java-tron.git +git checkout -t origin/master +``` + +* For Mac, you can also install **[GitHub for Mac](https://mac.github.com/)** then **[fork and clone our repository](https://guides.github.com/activities/forking/)**. + +* If you'd rather not use Git, [Download the ZIP](https://github.com/tronprotocol/java-tron/archive/develop.zip) + +## Including java-tron as dependency + +* If you don't want to checkout the code and build the project, you can include it directly as a dependency + +**Using gradle:** + +``` +repositories { + maven { url 'https://jitpack.io' } +} +dependencies { + implementation 'com.github.tronprotocol:java-tron:develop-SNAPSHOT' +} +``` + +**Using maven:** + +```xml +... + + + jitpack.io + https://jitpack.io + + +... + + com.github.tronprotocol + java-tron + develop-SNAPSHOT + +``` + + + + +## Building from source code + +* Build in the Terminal + +```bash +cd java-tron +./gradlew build +``` + + +* Build in [IntelliJ IDEA](https://www.jetbrains.com/idea/) (community version is enough): + + **Please run ./gradlew build once to build the protocol files** + + 1. Start IntelliJ. Select `File` -> `Open`, then locate to the java-tron folder which you have git cloned to your local drive. Then click `Open` button on the right bottom. + 2. Check on `Use auto-import` on the `Import Project from Gradle` dialog. Select JDK 1.8 in the `Gradle JVM` option. Then click `OK`. + 3. IntelliJ will open the project and start gradle syncing, which will take several minutes, depending on your network connection and your IntelliJ configuration + 4. Enable Annotations, `Preferences` -> Search `annotations` -> check `Enable Annotation Processing`. + 5. After the syncing finished, select `Gradle` -> `Tasks` -> `build`, and then double click `build` option. + \ No newline at end of file diff --git a/config/checkstyle/checkStyleAll.xml b/config/checkstyle/checkStyleAll.xml index dbce39c54f9..75d9d82bb6e 100644 --- a/config/checkstyle/checkStyleAll.xml +++ b/config/checkstyle/checkStyleAll.xml @@ -19,7 +19,7 @@ - + @@ -108,51 +108,51 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - + @@ -203,32 +203,32 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/images/architecture_diagram.png b/docs/images/architecture_diagram.png new file mode 100644 index 00000000000..01ec7a6915d Binary files /dev/null and b/docs/images/architecture_diagram.png differ diff --git a/prop.properties b/prop.properties new file mode 100644 index 00000000000..e69de29bb2d diff --git a/querySonar.sh b/querySonar.sh new file mode 100644 index 00000000000..ccc51fcba24 --- /dev/null +++ b/querySonar.sh @@ -0,0 +1,10 @@ + +PassFlag=`curl -s 'https://sonarcloud.io/api/project_badges/measure?project=java-tron&metric=alert_status'|grep -A4 "quality gate"|grep "pass"|wc -l` +echo "Please visit https://sonarcloud.io/dashboard?id=java-tron for more details" +if [ $PassFlag -eq 0 ]; then + echo "Sonar Check Failed" + exit 1 +else + echo "Sonar Check Pass" + exit 0 +fi diff --git a/quickstart.md b/quickstart.md new file mode 100644 index 00000000000..d3b5ec97703 --- /dev/null +++ b/quickstart.md @@ -0,0 +1,143 @@ +# How to quick start + +## Introduction + +This guide walks the user through the TRON Quickstart (v2.0.0) image setup. +The image exposes a Full Node, Solidity Node, and Event Server. Through TRON Quickstart, the user can deploy DApps, smart contracts, and interact via the TronWeb library. + +## Dependencies + +### Docker + +Please refer to the Docker official website to download and install the latest Docker version: +* Docker Installation for [Mac](https://docs.docker.com/docker-for-mac/install/) +* Docker Installation for [Windows](https://docs.docker.com/docker-for-windows/install/) + +### Node.JS Console + This will be used to interact with the Full and Solidity Nodes via Tron-Web. + [Node.JS](https://nodejs.org/en/) Console Download + +### Clone TRON Quickstart +```shell +git clone https://github.com/TRON-US/docker-tron-quickstart.git +``` + +### Pull the image using docker: +```shell +docker pull trontools/quickstart +``` + +## Setup TRON Quickstart +### TRON Quickstart Run +Run the docker run command to launch TRON Quickstart. TRON Quickstart exposes port 9090 for Full Node, Solidity Node, and Event Server. +```shell +docker run -it \ + -p 9090:9090 \ + --rm \ + --name tron \ + trontools/quickstart +``` + +**Run Output:** +```shell +[PM2] Spawning PM2 daemon with pm2_home=/root/.pm2 +[PM2] PM2 Successfully daemonized +[PM2][WARN] Applications eventron not running, starting... +[PM2] App [eventron] launched (1 instances) +┌──────────┬────┬─────────┬──────┬─────┬────────┬─────────┬────────┬─────┬───────────┬──────┬──────────┐ +│ App name │ id │ version │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ user │ watching │ +├──────────┼────┼─────────┼──────┼─────┼────────┼─────────┼────────┼─────┼───────────┼──────┼──────────┤ +│ eventron │ 0 │ N/A │ fork │ 60 │ online │ 0 │ 0s │ 0% │ 25.4 MB │ root │ disabled │ +└──────────┴────┴─────────┴──────┴─────┴────────┴─────────┴────────┴─────┴───────────┴──────┴──────────┘ + Use `pm2 show ` to get more details about an app +Start the http proxy for dApps... +[HPM] Proxy created: / -> http://127.0.0.1:18191 +[HPM] Proxy created: / -> http://127.0.0.1:18190 +[HPM] Proxy created: / -> http://127.0.0.1:8060 + + Tron Quickstart listening on http://127.0.0.1:9090 + + + +ADMIN /admin/accounts-generation +Sleeping for 1 second...Waiting when nodes are ready to generate 10 accounts... +(1) Waiting for sync... + Slept. +... +Loading the accounts and waiting for the node to mine the transactions... +(1) Waiting for receipts... +Sending 10000 TRX to TSjfWSWcKCrJ1DbgMZSCbSqNK8DsEfqM9p +Sending 10000 TRX to THpWnj3dBQ5FrqW1KMVXXYSbHPtcBKeUJY +Sending 10000 TRX to TWFTHaKdeHWi3oPoaBokyZFfA7q1iiiAAb +Sending 10000 TRX to TFDGQo6f6dm9ikoV4Rc9NyTxMD5NNiSFJD +Sending 10000 TRX to TDZZNigWitFp5aE6j2j8YcycF7DVjtogBu +Sending 10000 TRX to TT8NRMcwdS9P3X9pvPC8JWi3x2zjwxZuhs +Sending 10000 TRX to TBBJw6Bk7w2NSZeqmzfUPnsn6CwDJAXTv8 +Sending 10000 TRX to TVcgSLpT97mvoiyv5ChyhQ6hWbjYLWdCVB +Sending 10000 TRX to TYjQd4xrLZQGYMdLJqsTCuXVGapPqUp9ZX +Sending 10000 TRX to THCw6hPZpFcLCWDcsZg3W77rXZ9rJQPncD +Sleeping for 3 seconds... Slept. +(2) Waiting for receipts... +Sleeping for 3 seconds... Slept. +(3) Waiting for receipts... +Sleeping for 3 seconds... Slept. +(4) Waiting for receipts... +Sleeping for 3 seconds... Slept. +(5) Waiting for receipts... +Sleeping for 3 seconds... Slept. +(6) Waiting for receipts... +Sleeping for 3 seconds... Slept. +(7) Waiting for receipts... +Done. + +Available Accounts +================== + +(0) TSjfWSWcKCrJ1DbgMZSCbSqNK8DsEfqM9p (10000 TRX) +(1) THpWnj3dBQ5FrqW1KMVXXYSbHPtcBKeUJY (10000 TRX) +(2) TWFTHaKdeHWi3oPoaBokyZFfA7q1iiiAAb (10000 TRX) +(3) TFDGQo6f6dm9ikoV4Rc9NyTxMD5NNiSFJD (10000 TRX) +(4) TDZZNigWitFp5aE6j2j8YcycF7DVjtogBu (10000 TRX) +(5) TT8NRMcwdS9P3X9pvPC8JWi3x2zjwxZuhs (10000 TRX) +(6) TBBJw6Bk7w2NSZeqmzfUPnsn6CwDJAXTv8 (10000 TRX) +(7) TVcgSLpT97mvoiyv5ChyhQ6hWbjYLWdCVB (10000 TRX) +(8) TYjQd4xrLZQGYMdLJqsTCuXVGapPqUp9ZX (10000 TRX) +(9) THCw6hPZpFcLCWDcsZg3W77rXZ9rJQPncD (10000 TRX) + +Private Keys +================== + +(0) 2b2bddbeea87cecedcaf51eef55877b65725f709d2c0fcdfea0cb52d80acd52b +(1) f08759925316dc6344af538ebe3a619aeab836a0c254adca903cc764f87b0ee9 +(2) 1afc9f033cf9c6058db366b78a9f1b9c909b1b83397c9aed795afa05e9017511 +(3) f8f5bc70e91fc177eefea43b68c97b66536ac317a9300639e9d32a9db2f18a1f +(4) 031015272915917056c117d3cc2a03491a8f22ef450af83f6783efddf7064c59 +(5) 5eb25e2c1144f216aa99bbe2139d84bb6dedfb2c1ed72f3df6684a4c6d2cd96b +(6) f0b781da23992e6a3f536cb60917c3eb6a9c5434fcf441fcb8d7c58c01d6b70e +(7) 158f60a4379688a77d4a420e2f2a3e014ebf9ed0a1a093d7dc01ba23ebc5c970 +(8) e9342bb9108f46573804890a5301530c2834dce3703cd51ab77fba6161afec00 +(9) 2e9f0c507d2ea98dc4005a1afb1b743c629f7c145ccb55f38f75ae73cf8f605c + +HD Wallet +================== +Mnemonic: border pulse twenty cruise grief shy need raw clean possible begin climb +Base HD Path: m/44'/60'/0'/0/{account_index} +``` +## Docker Commands +A few Docker commands are useful for managing the TRON Quickstart Docker container on your machine. + +**To list all active containers on your machine, run:** +```shell +docker container ps +``` +**Output:** +```shell +docker container ps + +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +513078dc7816 tron "./quickstart v2.0.0" About an hour ago Up About an hour 0.0.0.0:9090->9090/tcp, 0.0.0.0:18190->18190/tcp tron +``` +**To kill an active container, run:** +```shell +docker container kill 513078dc7816 // use your container ID +``` diff --git a/run.md b/run.md new file mode 100644 index 00000000000..ecd105f9020 --- /dev/null +++ b/run.md @@ -0,0 +1,193 @@ +# How to Running + +### Running multi-nodes + +https://github.com/tronprotocol/Documentation/blob/master/TRX/Solidity_and_Full_Node_Deployment_EN.md + +## Running a local node and connecting to the public testnet + +* Use the [Testnet Config](https://github.com/tronprotocol/TronDeployment/blob/master/test_net_config.conf) or use the [Tron Deployment Scripts](https://github.com/tronprotocol/TronDeployment) + + +### Running a Super Representative Node for mainnet + +* Use the executable JAR(Recommended way) + +```bash +java -jar FullNode.jar -p your private key --witness -c your config.conf(Example:/data/java-tron/config.conf) +Example: +java -jar FullNode.jar -p 650950B193DDDDB35B6E48912DD28F7AB0E7140C1BFDEFD493348F02295BD812 --witness -c /data/java-tron/config.conf + +``` + +This is similar to running a private testnet, except that the IPs in the `config.conf` are officially declared by TRON. + +
+Correct output + +```bash + +20:43:18.138 INFO [main] [o.t.p.FullNode](FullNode.java:21) Full node running. +20:43:18.486 INFO [main] [o.t.c.c.a.Args](Args.java:429) Bind address wasn't set, Punching to identify it... +20:43:18.493 INFO [main] [o.t.c.c.a.Args](Args.java:433) UDP local bound to: 10.0.8.146 +20:43:18.495 INFO [main] [o.t.c.c.a.Args](Args.java:448) External IP wasn't set, using checkip.amazonaws.com to identify it... +20:43:19.450 INFO [main] [o.t.c.c.a.Args](Args.java:461) External address identified: 47.74.147.87 +20:43:19.599 INFO [main] [o.s.c.a.AnnotationConfigApplicationContext](AbstractApplicationContext.java:573) Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@124c278f: startup date [Fri Apr 27 20:43:19 CST 2018]; root of context hierarchy +20:43:19.972 INFO [main] [o.s.b.f.a.AutowiredAnnotationBeanPostProcessor](AutowiredAnnotationBeanPostProcessor.java:153) JSR-330 'javax.inject.Inject' annotation found and supported for autowiring +20:43:20.380 INFO [main] [o.t.c.d.DynamicPropertiesStore](DynamicPropertiesStore.java:244) update latest block header timestamp = 0 +20:43:20.383 INFO [main] [o.t.c.d.DynamicPropertiesStore](DynamicPropertiesStore.java:252) update latest block header number = 0 +20:43:20.393 INFO [main] [o.t.c.d.DynamicPropertiesStore](DynamicPropertiesStore.java:260) update latest block header id = 00 +20:43:20.394 INFO [main] [o.t.c.d.DynamicPropertiesStore](DynamicPropertiesStore.java:265) update state flag = 0 +20:43:20.559 INFO [main] [o.t.c.c.TransactionCapsule](TransactionCapsule.java:83) Transaction create succeeded! +20:43:20.567 INFO [main] [o.t.c.c.TransactionCapsule](TransactionCapsule.java:83) Transaction create succeeded! +20:43:20.568 INFO [main] [o.t.c.c.TransactionCapsule](TransactionCapsule.java:83) Transaction create succeeded! +20:43:20.568 INFO [main] [o.t.c.c.TransactionCapsule](TransactionCapsule.java:83) Transaction create succeeded! +20:43:20.569 INFO [main] [o.t.c.c.TransactionCapsule](TransactionCapsule.java:83) Transaction create succeeded! +20:43:20.596 INFO [main] [o.t.c.d.Manager](Manager.java:300) create genesis block +20:43:20.607 INFO [main] [o.t.c.d.Manager](Manager.java:306) save block: BlockCapsule + +``` + +Then observe whether block synchronization success,If synchronization successfully explains the success of the super node + +
+ + +### Running a Super Representative Node for private testnet +* use master branch +* You should modify the config.conf + 1. Replace existing entry in genesis.block.witnesses with your address. + 2. Replace existing entry in seed.node ip.list with your ip list. + 3. The first Super Node start, needSyncCheck should be set false + 4. Set p2pversion to 61 + +* Use the executable JAR(Recommended way) + +```bash +cd build/libs +java -jar FullNode.jar -p your private key --witness -c your config.conf (Example:/data/java-tron/config.conf) +Example: +java -jar FullNode.jar -p 650950B193DDDDB35B6E48912DD28F7AB0E7140C1BFDEFD493348F02295BD812 --witness -c /data/java-tron/config.conf + +``` + +
+Show Output + +```bash +> ./gradlew run -Pwitness + +> Task :generateProto UP-TO-DATE +Using TaskInputs.file() with something that doesn't resolve to a File object has been deprecated and is scheduled to be removed in Gradle 5.0. Use TaskInputs.files() instead. + +> Task :run +20:39:22.749 INFO [o.t.c.c.a.Args] private.key = 63e62a71ed39e30bac7223097a173924aad5855959de517ff2987b0e0ec89f1a +20:39:22.816 WARN [o.t.c.c.a.Args] localwitness size must be one, get the first one +20:39:22.832 INFO [o.t.p.FullNode] Here is the help message.output-directory/ +三月 22, 2018 8:39:23 下午 org.tron.core.services.RpcApiService start +信息: Server started, listening on 50051 +20:39:23.706 INFO [o.t.c.o.n.GossipLocalNode] listener message +20:39:23.712 INFO [o.t.c.o.n.GossipLocalNode] sync group = a41d27f10194c53703be90c6f8735bb66ffc53aa10ea9024d92dbe7324b1aee3 +20:39:23.716 INFO [o.t.c.s.WitnessService] Sleep : 1296 ms,next time:2018-03-22T20:39:25.000+08:00 +20:39:23.734 WARN [i.s.t.BootstrapFactory] Env doesn't support epoll transport +20:39:23.746 INFO [i.s.t.TransportImpl] Bound to: 192.168.10.163:7080 +20:39:23.803 INFO [o.t.c.n.n.NodeImpl] other peer is nil, please wait ... +20:39:25.019 WARN [o.t.c.d.Manager] nextFirstSlotTime:[2018-03-22T17:57:20.001+08:00],now[2018-03-22T20:39:25.067+08:00] +20:39:25.019 INFO [o.t.c.s.WitnessService] ScheduledWitness[448d53b2df0cd78158f6f0aecdf60c1c10b15413],slot[1946] +20:39:25.021 INFO [o.t.c.s.WitnessService] It's not my turn +20:39:25.021 INFO [o.t.c.s.WitnessService] Sleep : 4979 ms,next time:2018-03-22T20:39:30.000+08:00 +20:39:30.003 WARN [o.t.c.d.Manager] nextFirstSlotTime:[2018-03-22T17:57:20.001+08:00],now[2018-03-22T20:39:30.052+08:00] +20:39:30.003 INFO [o.t.c.s.WitnessService] ScheduledWitness[6c22c1af7bfbb2b0e07148ecba27b56f81a54fcf],slot[1947] +20:39:30.003 INFO [o.t.c.s.WitnessService] It's not my turn +20:39:30.003 INFO [o.t.c.s.WitnessService] Sleep : 4997 ms,next time:2018-03-22T20:39:35.000+08:00 +20:39:33.803 INFO [o.t.c.n.n.NodeImpl] other peer is nil, please wait ... +20:39:35.005 WARN [o.t.c.d.Manager] nextFirstSlotTime:[2018-03-22T17:57:20.001+08:00],now[2018-03-22T20:39:35.054+08:00] +20:39:35.005 INFO [o.t.c.s.WitnessService] ScheduledWitness[48e447ec869216de76cfeeadf0db37a3d1c8246d],slot[1948] +20:39:35.005 INFO [o.t.c.s.WitnessService] It's not my turn +20:39:35.005 INFO [o.t.c.s.WitnessService] Sleep : 4995 ms,next time:2018-03-22T20:39:40.000+08:00 +20:39:40.005 WARN [o.t.c.d.Manager] nextFirstSlotTime:[2018-03-22T17:57:20.001+08:00],now[2018-03-22T20:39:40.055+08:00] +20:39:40.010 INFO [o.t.c.d.Manager] postponedTrxCount[0],TrxLeft[0] +20:39:40.022 INFO [o.t.c.d.DynamicPropertiesStore] update latest block header id = fd30a16160715f3ca1a5bcad18e81991cd6f47265a71815bd2c943129b258cd2 +20:39:40.022 INFO [o.t.c.d.TronStoreWithRevoking] Address is [108, 97, 116, 101, 115, 116, 95, 98, 108, 111, 99, 107, 95, 104, 101, 97, 100, 101, 114, 95, 104, 97, 115, 104], BytesCapsule is org.tron.core.capsule.BytesCapsule@2ce0e954 +20:39:40.023 INFO [o.t.c.d.DynamicPropertiesStore] update latest block header number = 140 +20:39:40.024 INFO [o.t.c.d.TronStoreWithRevoking] Address is [108, 97, 116, 101, 115, 116, 95, 98, 108, 111, 99, 107, 95, 104, 101, 97, 100, 101, 114, 95, 110, 117, 109, 98, 101, 114], BytesCapsule is org.tron.core.capsule.BytesCapsule@83924ab +20:39:40.024 INFO [o.t.c.d.DynamicPropertiesStore] update latest block header timestamp = 1521722380001 +20:39:40.024 INFO [o.t.c.d.TronStoreWithRevoking] Address is [108, 97, 116, 101, 115, 116, 95, 98, 108, 111, 99, 107, 95, 104, 101, 97, 100, 101, 114, 95, 116, 105, 109, 101, 115, 116, 97, 109, 112], BytesCapsule is org.tron.core.capsule.BytesCapsule@ca6a6f8 +20:39:40.024 INFO [o.t.c.d.Manager] updateWitnessSchedule number:140,HeadBlockTimeStamp:1521722380001 +20:39:40.025 WARN [o.t.c.u.RandomGenerator] index[-3] is out of range[0,3],skip +20:39:40.070 INFO [o.t.c.d.TronStoreWithRevoking] Address is [73, 72, -62, -24, -89, 86, -39, 67, 112, 55, -36, -40, -57, -32, -57, 61, 86, 12, -93, -115], AccountCapsule is account_name: "Sun" +address: "IH\302\350\247V\331Cp7\334\330\307\340\307=V\f\243\215" +balance: 9223372036854775387 + +20:39:40.081 INFO [o.t.c.d.TronStoreWithRevoking] Address is [41, -97, 61, -72, 10, 36, -78, 10, 37, 75, -119, -50, 99, -99, 89, 19, 47, 21, 127, 19], AccountCapsule is type: AssetIssue +address: ")\237=\270\n$\262\n%K\211\316c\235Y\023/\025\177\023" +balance: 420 + +20:39:40.082 INFO [o.t.c.d.TronStoreWithRevoking] Address is [76, 65, 84, 69, 83, 84, 95, 83, 79, 76, 73, 68, 73, 70, 73, 69, 68, 95, 66, 76, 79, 67, 75, 95, 78, 85, 77], BytesCapsule is org.tron.core.capsule.BytesCapsule@ec1439 +20:39:40.083 INFO [o.t.c.d.Manager] there is account List size is 8 +20:39:40.084 INFO [o.t.c.d.Manager] there is account ,account address is 448d53b2df0cd78158f6f0aecdf60c1c10b15413 +20:39:40.084 INFO [o.t.c.d.Manager] there is account ,account address is 548794500882809695a8a687866e76d4271a146a +20:39:40.084 INFO [o.t.c.d.Manager] there is account ,account address is 48e447ec869216de76cfeeadf0db37a3d1c8246d +20:39:40.084 INFO [o.t.c.d.Manager] there is account ,account address is 55ddae14564f82d5b94c7a131b5fcfd31ad6515a +20:39:40.085 INFO [o.t.c.d.Manager] there is account ,account address is 6c22c1af7bfbb2b0e07148ecba27b56f81a54fcf +20:39:40.085 INFO [o.t.c.d.Manager] there is account ,account address is 299f3db80a24b20a254b89ce639d59132f157f13 +20:39:40.085 INFO [o.t.c.d.Manager] there is account ,account address is abd4b9367799eaa3197fecb144eb71de1e049150 +20:39:40.085 INFO [o.t.c.d.Manager] there is account ,account address is 4948c2e8a756d9437037dcd8c7e0c73d560ca38d +20:39:40.085 INFO [o.t.c.d.TronStoreWithRevoking] Address is [108, 34, -63, -81, 123, -5, -78, -80, -32, 113, 72, -20, -70, 39, -75, 111, -127, -91, 79, -49], WitnessCapsule is org.tron.core.capsule.WitnessCapsule@4cb4f7fb +20:39:40.086 INFO [o.t.c.d.TronStoreWithRevoking] Address is [41, -97, 61, -72, 10, 36, -78, 10, 37, 75, -119, -50, 99, -99, 89, 19, 47, 21, 127, 19], WitnessCapsule is org.tron.core.capsule.WitnessCapsule@7be2474a +20:39:40.086 INFO [o.t.c.d.TronStoreWithRevoking] Address is [72, -28, 71, -20, -122, -110, 22, -34, 118, -49, -18, -83, -16, -37, 55, -93, -47, -56, 36, 109], WitnessCapsule is org.tron.core.capsule.WitnessCapsule@3e375891 +20:39:40.086 INFO [o.t.c.d.TronStoreWithRevoking] Address is [68, -115, 83, -78, -33, 12, -41, -127, 88, -10, -16, -82, -51, -10, 12, 28, 16, -79, 84, 19], WitnessCapsule is org.tron.core.capsule.WitnessCapsule@55d77b83 +20:39:40.090 INFO [o.t.c.d.Manager] countWitnessMap size is 0 +20:39:40.091 INFO [o.t.c.d.TronStoreWithRevoking] Address is [41, -97, 61, -72, 10, 36, -78, 10, 37, 75, -119, -50, 99, -99, 89, 19, 47, 21, 127, 19], WitnessCapsule is org.tron.core.capsule.WitnessCapsule@310dd876 +20:39:40.092 INFO [o.t.c.d.TronStoreWithRevoking] Address is [72, -28, 71, -20, -122, -110, 22, -34, 118, -49, -18, -83, -16, -37, 55, -93, -47, -56, 36, 109], WitnessCapsule is org.tron.core.capsule.WitnessCapsule@151b42bc +20:39:40.092 INFO [o.t.c.d.TronStoreWithRevoking] Address is [108, 34, -63, -81, 123, -5, -78, -80, -32, 113, 72, -20, -70, 39, -75, 111, -127, -91, 79, -49], WitnessCapsule is org.tron.core.capsule.WitnessCapsule@2d0388aa +20:39:40.092 INFO [o.t.c.d.TronStoreWithRevoking] Address is [68, -115, 83, -78, -33, 12, -41, -127, 88, -10, -16, -82, -51, -10, 12, 28, 16, -79, 84, 19], WitnessCapsule is org.tron.core.capsule.WitnessCapsule@478a55e7 +20:39:40.101 INFO [o.t.c.d.TronStoreWithRevoking] Address is [-3, 48, -95, 97, 96, 113, 95, 60, -95, -91, -68, -83, 24, -24, 25, -111, -51, 111, 71, 38, 90, 113, -127, 91, -46, -55, 67, 18, -101, 37, -116, -46], BlockCapsule is BlockCapsule{blockId=fd30a16160715f3ca1a5bcad18e81991cd6f47265a71815bd2c943129b258cd2, num=140, parentId=dadeff07c32d342b941cfa97ba82870958615e7ae73fffeaf3c6a334d81fe3bd, generatedByMyself=true} +20:39:40.102 INFO [o.t.c.d.Manager] save block: BlockCapsule{blockId=fd30a16160715f3ca1a5bcad18e81991cd6f47265a71815bd2c943129b258cd2, num=140, parentId=dadeff07c32d342b941cfa97ba82870958615e7ae73fffeaf3c6a334d81fe3bd, generatedByMyself=true} +20:39:40.102 INFO [o.t.c.s.WitnessService] Block is generated successfully, Its Id is fd30a16160715f3ca1a5bcad18e81991cd6f47265a71815bd2c943129b258cd2,number140 +20:39:40.102 INFO [o.t.c.n.n.NodeImpl] Ready to broadcast a block, Its hash is fd30a16160715f3ca1a5bcad18e81991cd6f47265a71815bd2c943129b258cd2 +20:39:40.107 INFO [o.t.c.s.WitnessService] Produced +20:39:40.107 INFO [o.t.c.s.WitnessService] Sleep : 4893 ms,next time:2018-03-22T20:39:45.000+08:00 +20:39:43.805 INFO [o.t.c.n.n.NodeImpl] other peer is nil, please wait ... +20:39:45.002 WARN [o.t.c.d.Manager] nextFirstSlotTime:[2018-03-22T20:39:45.001+08:00],now[2018-03-22T20:39:45.052+08:00] +20:39:45.003 INFO [o.t.c.s.WitnessService] ScheduledWitness[48e447ec869216de76cfeeadf0db37a3d1c8246d],slot[1] +20:39:45.003 INFO [o.t.c.s.WitnessService] It's not my turn +20:39:45.003 INFO [o.t.c.s.WitnessService] Sleep : 4997 ms,next time:2018-03-22T20:39:50.000+08:00 +20:39:50.002 WARN [o.t.c.d.Manager] nextFirstSlotTime:[2018-03-22T20:39:45.001+08:00],now[2018-03-22T20:39:50.052+08:00] +20:39:50.003 INFO [o.t.c.s.WitnessService] ScheduledWitness[6c22c1af7bfbb2b0e07148ecba27b56f81a54fcf],slot[2] +20:39:50.003 INFO [o.t.c.s.WitnessService] It's not my turn +20:39:50.003 INFO [o.t.c.s.WitnessService] Sleep : 4997 ms,next time:2018-03-22T20:39:55.000+08:00 + +``` + +
+ +* In IntelliJ IDEA + +
+ + +Open the configuration panel: + + + +![](docs/images/program_configure.png) + +
+ +
+ + +In the `Program arguments` option, fill in `--witness`: + + + +![](docs/images/set_witness_param.jpeg) + +
+ +Then, run `FullNode::main()` again. + +## Advanced Configurations + +Read the [Advanced Configurations](src/main/java/org/tron/core/config/README.md). diff --git a/src/main/java/org/tron/common/backup/BackupManager.java b/src/main/java/org/tron/common/backup/BackupManager.java index 40244fa05c7..a067dd9ab40 100644 --- a/src/main/java/org/tron/common/backup/BackupManager.java +++ b/src/main/java/org/tron/common/backup/BackupManager.java @@ -37,9 +37,9 @@ public class BackupManager implements EventHandler { private ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); - private volatile MessageHandler messageHandler; + private MessageHandler messageHandler; - private volatile BackupStatusEnum status = MASTER; + private BackupStatusEnum status = MASTER; private volatile long lastKeepAliveTime; diff --git a/src/main/java/org/tron/common/crypto/Hash.java b/src/main/java/org/tron/common/crypto/Hash.java index 574d2dc03e4..d0eca69176d 100644 --- a/src/main/java/org/tron/common/crypto/Hash.java +++ b/src/main/java/org/tron/common/crypto/Hash.java @@ -19,6 +19,7 @@ package org.tron.common.crypto; import static java.util.Arrays.copyOfRange; +import static org.tron.common.utils.ByteUtil.EMPTY_BYTE_ARRAY; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -27,6 +28,7 @@ import lombok.extern.slf4j.Slf4j; import org.tron.common.crypto.jce.TronCastleProvider; import org.tron.core.Wallet; +import org.tron.core.capsule.utils.RLP; @Slf4j(topic = "crypto") public class Hash { @@ -36,11 +38,14 @@ public class Hash { private static final String HASH_256_ALGORITHM_NAME; private static final String HASH_512_ALGORITHM_NAME; + public static final byte[] EMPTY_TRIE_HASH; + static { Security.addProvider(TronCastleProvider.getInstance()); CRYPTO_PROVIDER = Security.getProvider("SC"); HASH_256_ALGORITHM_NAME = "TRON-KECCAK-256"; HASH_512_ALGORITHM_NAME = "TRON-KECCAK-512"; + EMPTY_TRIE_HASH = sha3(RLP.encodeElement(EMPTY_BYTE_ARRAY)); } public static byte[] sha3(byte[] input) { diff --git a/src/main/java/org/tron/common/logsfilter/ContractEventParser.java b/src/main/java/org/tron/common/logsfilter/ContractEventParser.java index 31e4b36b8d7..e999e18ed68 100644 --- a/src/main/java/org/tron/common/logsfilter/ContractEventParser.java +++ b/src/main/java/org/tron/common/logsfilter/ContractEventParser.java @@ -1,24 +1,16 @@ package org.tron.common.logsfilter; import java.math.BigInteger; -import java.util.HashMap; -import java.util.List; -import java.util.Map; import java.util.regex.Pattern; - -import com.sun.org.apache.xpath.internal.operations.Mult; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; import org.pf4j.util.StringUtils; import org.spongycastle.crypto.OutputLengthException; import org.spongycastle.util.Arrays; import org.spongycastle.util.encoders.Hex; -import org.tron.common.crypto.Hash; import org.tron.common.runtime.utils.MUtil; import org.tron.common.runtime.vm.DataWord; -import org.tron.common.utils.ByteArray; import org.tron.core.Wallet; -import org.tron.protos.Protocol.SmartContract.ABI; @Slf4j(topic = "Parser") public class ContractEventParser { @@ -36,110 +28,7 @@ private enum Type { BYTES, } - /** - * parse Event Topic into map NOTICE: In solidity, Indexed Dynamic types's topic is just - * EVENT_INDEXED_ARGS - */ - public static Map parseTopics(List topicList, ABI.Entry entry) { - Map map = new HashMap<>(); - if (topicList == null || topicList.isEmpty()) { - return map; - } - - // the first is the signature. - int index = 1; - List list = entry.getInputsList(); - - // in case indexed topics doesn't match - if (topicsMatched(topicList, entry)) { - for (int i = 0; i < list.size(); ++i) { - ABI.Entry.Param param = list.get(i); - if (!param.getIndexed()) { - continue; - } - - if (index >= topicList.size()) { - break; - } - String str = parseTopic(topicList.get(index++), param.getType()); - if (StringUtils.isNotNullOrEmpty(param.getName())) { - map.put(param.getName(), str); - } - map.put("" + i, str); - } - } else { - for (int i = 1; i < topicList.size(); ++i) { - map.put("" + (i - 1), Hex.toHexString(topicList.get(i))); - } - } - return map; - } - - /** - * parse Event Data into map If parser failed, then return {"0", - * Hex.toHexString(data)} Only support basic solidity type, String, Bytes. Fixed Array or dynamic - * Array are not support yet (then return {"0": Hex.toHexString(data)}). - */ - public static Map parseEventData(byte[] data, - List topicList, ABI.Entry entry) { - Map map = new HashMap<>(); - if (ArrayUtils.isEmpty(data)) { - return map; - } - // in case indexed topics doesn't match - if (!topicsMatched(topicList, entry)) { - map.put("" + (topicList.size() - 1), Hex.toHexString(data)); - return map; - } - - // the first is the signature. - List list = entry.getInputsList(); - Integer startIndex = 0; - try { - // this one starts from the first position. - int index = 0; - for (Integer i = 0; i < list.size(); ++i) { - ABI.Entry.Param param = list.get(i); - if (param.getIndexed()) { - continue; - } - if (startIndex == 0) { - startIndex = i; - } - - String str = parseDataBytes(data, param.getType(), index++); - if (StringUtils.isNotNullOrEmpty(param.getName())) { - map.put(param.getName(), str); - } - map.put("" + i, str); - - } - if (list.size() == 0) { - map.put("0", Hex.toHexString(data)); - } - } catch (UnsupportedOperationException e) { - logger.debug("UnsupportedOperationException", e); - map.clear(); - map.put(startIndex.toString(), Hex.toHexString(data)); - } - return map; - } - - private static boolean topicsMatched(List topicList, ABI.Entry entry) { - if (topicList == null || topicList.isEmpty()) { - return true; - } - int inputSize = 1; - for (ABI.Entry.Param param : entry.getInputsList()) { - if (param.getIndexed()) { - inputSize++; - } - } - return inputSize == topicList.size(); - } - - private static String parseDataBytes(byte[] data, String typeStr, int index) { - + protected static String parseDataBytes(byte[] data, String typeStr, int index) { try { byte[] startBytes = subBytes(data, index * DATAWORD_UNIT_SIZE, DATAWORD_UNIT_SIZE); Type type = basicType(typeStr); @@ -158,7 +47,8 @@ private static String parseDataBytes(byte[] data, String typeStr, int index) { byte[] lengthBytes = subBytes(data, start, DATAWORD_UNIT_SIZE); // this length is byte count. no need X 32 int length = intValueExact(lengthBytes); - byte[] realBytes = subBytes(data, start + DATAWORD_UNIT_SIZE, length); + byte[] realBytes = + length > 0 ? subBytes(data, start + DATAWORD_UNIT_SIZE, length) : new byte[0]; return type == Type.STRING ? new String(realBytes) : Hex.toHexString(realBytes); } } catch (OutputLengthException | ArithmeticException e) { @@ -168,31 +58,31 @@ private static String parseDataBytes(byte[] data, String typeStr, int index) { } // don't support these type yet : bytes32[10][10] OR bytes32[][10] - private static Type basicType(String type) { + protected static Type basicType(String type) { if (!Pattern.matches("^.*\\[\\d*\\]$", type)) { // ignore not valide type such as "int92", "bytes33", these types will be compiled failed. if (type.startsWith("int") || type.startsWith("uint") || type.startsWith("trcToken")) { return Type.INT_NUMBER; - } else if (type.equals("bool")) { + } else if ("bool".equals(type)) { return Type.BOOL; - } else if (type.equals("address")) { + } else if ("address".equals(type)) { return Type.ADDRESS; } else if (Pattern.matches("^bytes\\d+$", type)) { return Type.FIXED_BYTES; - } else if (type.equals("string")) { + } else if ("string".equals(type)) { return Type.STRING; - } else if (type.equals("bytes")) { + } else if ("bytes".equals(type)) { return Type.BYTES; } } return Type.UNKNOWN; } - private static Integer intValueExact(byte[] data) { + protected static Integer intValueExact(byte[] data) { return new BigInteger(data).intValueExact(); } - private static byte[] subBytes(byte[] src, int start, int length) { + protected static byte[] subBytes(byte[] src, int start, int length) { if (ArrayUtils.isEmpty(src) || start >= src.length || length < 0) { throw new OutputLengthException("data start:" + start + ", length:" + length); } @@ -210,7 +100,7 @@ private static byte[] subBytes(byte[] src, int start, int length) { * This is only for decode Topic. Since Topic and Data use different encode methods when deal * dynamic length types, such as bytes and string. */ - private static String parseTopic(byte[] bytes, String typeStr) { + protected static String parseTopic(byte[] bytes, String typeStr) { if (ArrayUtils.isEmpty(bytes) || StringUtils.isNullOrEmpty(typeStr)) { return ""; } diff --git a/src/main/java/org/tron/common/logsfilter/ContractEventParserAbi.java b/src/main/java/org/tron/common/logsfilter/ContractEventParserAbi.java new file mode 100644 index 00000000000..d382b65450b --- /dev/null +++ b/src/main/java/org/tron/common/logsfilter/ContractEventParserAbi.java @@ -0,0 +1,114 @@ +package org.tron.common.logsfilter; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ArrayUtils; +import org.pf4j.util.StringUtils; +import org.spongycastle.util.encoders.Hex; +import org.tron.protos.Protocol.SmartContract.ABI; + +@Slf4j(topic = "Parser") +public class ContractEventParserAbi extends ContractEventParser { + + /** + * parse Event Topic into map NOTICE: In solidity, Indexed Dynamic types's topic is just + * EVENT_INDEXED_ARGS + */ + public static Map parseTopics(List topicList, ABI.Entry entry) { + Map map = new HashMap<>(); + if (topicList == null || topicList.isEmpty()) { + return map; + } + + // the first is the signature. + int index = 1; + List list = entry.getInputsList(); + + // in case indexed topics doesn't match + if (topicsMatched(topicList, entry)) { + for (int i = 0; i < list.size(); ++i) { + ABI.Entry.Param param = list.get(i); + if (param.getIndexed()) { + if (index >= topicList.size()) { + break; + } + String str = parseTopic(topicList.get(index++), param.getType()); + if (StringUtils.isNotNullOrEmpty(param.getName())) { + map.put(param.getName(), str); + } + map.put("" + i, str); + } + } + } else { + for (int i = 1; i < topicList.size(); ++i) { + map.put("" + (i - 1), Hex.toHexString(topicList.get(i))); + } + } + return map; + } + + /** + * parse Event Data into map If parser failed, then return {"0", + * Hex.toHexString(data)} Only support basic solidity type, String, Bytes. Fixed Array or dynamic + * Array are not support yet (then return {"0": Hex.toHexString(data)}). + */ + public static Map parseEventData(byte[] data, + List topicList, ABI.Entry entry) { + Map map = new HashMap<>(); + if (ArrayUtils.isEmpty(data)) { + return map; + } + // in case indexed topics doesn't match + if (!topicsMatched(topicList, entry)) { + map.put("" + (topicList.size() - 1), Hex.toHexString(data)); + return map; + } + + // the first is the signature. + List list = entry.getInputsList(); + Integer startIndex = 0; + try { + // this one starts from the first position. + int index = 0; + for (Integer i = 0; i < list.size(); ++i) { + ABI.Entry.Param param = list.get(i); + if (param.getIndexed()) { + continue; + } + if (startIndex == 0) { + startIndex = i; + } + + String str = parseDataBytes(data, param.getType(), index++); + if (StringUtils.isNotNullOrEmpty(param.getName())) { + map.put(param.getName(), str); + } + map.put("" + i, str); + + } + if (list.size() == 0) { + map.put("0", Hex.toHexString(data)); + } + } catch (UnsupportedOperationException e) { + logger.debug("UnsupportedOperationException", e); + map.clear(); + map.put(startIndex.toString(), Hex.toHexString(data)); + } + return map; + } + + private static boolean topicsMatched(List topicList, ABI.Entry entry) { + if (topicList == null || topicList.isEmpty()) { + return true; + } + int inputSize = 1; + for (ABI.Entry.Param param : entry.getInputsList()) { + if (param.getIndexed()) { + inputSize++; + } + } + return inputSize == topicList.size(); + } +} diff --git a/src/main/java/org/tron/common/logsfilter/ContractEventParserJson.java b/src/main/java/org/tron/common/logsfilter/ContractEventParserJson.java new file mode 100644 index 00000000000..c74b2f882d4 --- /dev/null +++ b/src/main/java/org/tron/common/logsfilter/ContractEventParserJson.java @@ -0,0 +1,128 @@ +package org.tron.common.logsfilter; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ArrayUtils; +import org.pf4j.util.StringUtils; +import org.spongycastle.util.encoders.Hex; + +@Slf4j(topic = "Parser") +public class ContractEventParserJson extends ContractEventParser { + + private static final String INPUTS = "inputs"; + private static final String INDEXED = "indexed"; + + /** + * parse Event Topic into map NOTICE: In solidity, Indexed Dynamic types's topic is just + * EVENT_INDEXED_ARGS + */ + public static Map parseTopics(List topicList, JSONObject entry) { + Map map = new HashMap<>(); + if (topicList == null || topicList.isEmpty()) { + return map; + } + + // the first is the signature. + int index = 1; + JSONArray inputs = entry.getJSONArray(INPUTS); + + // in case indexed topics doesn't match + if (topicsMatched(topicList, entry)) { + for (int i = 0; i < inputs.size(); ++i) { + JSONObject param = inputs.getJSONObject(i); + Boolean indexed = param.getBoolean(INDEXED); + if (indexed == null || !indexed) { + continue; + } + if (index >= topicList.size()) { + break; + } + String str = parseTopic(topicList.get(index++), param.getString("type")); + if (StringUtils.isNotNullOrEmpty(param.getString("name"))) { + map.put(param.getString("name"), str); + } + map.put("" + i, str); + } + } else { + for (int i = 1; i < topicList.size(); ++i) { + map.put("" + (i - 1), Hex.toHexString(topicList.get(i))); + } + } + return map; + } + + /** + * parse Event Data into map If parser failed, then return {"0", + * Hex.toHexString(data)} Only support basic solidity type, String, Bytes. Fixed Array or dynamic + * Array are not support yet (then return {"0": Hex.toHexString(data)}). + */ + public static Map parseEventData(byte[] data, + List topicList, JSONObject entry) { + Map map = new HashMap<>(); + if (ArrayUtils.isEmpty(data)) { + return map; + } + // in case indexed topics doesn't match + if (!topicsMatched(topicList, entry)) { + map.put("" + (topicList.size() - 1), Hex.toHexString(data)); + return map; + } + + // the first is the signature. + JSONArray inputs = entry.getJSONArray(INPUTS); + Integer startIndex = 0; + + try { + // this one starts from the first position. + int index = 0; + if (inputs != null) { + for (Integer i = 0; i < inputs.size(); ++i) { + JSONObject param = inputs.getJSONObject(i); + Boolean indexed = param.getBoolean(INDEXED); + if (indexed != null && indexed) { + continue; + } + + if (startIndex == 0) { + startIndex = i; + } + + String str = parseDataBytes(data, param.getString("type"), index++); + if (StringUtils.isNotNullOrEmpty(param.getString("name"))) { + map.put(param.getString("name"), str); + } + map.put("" + i, str); + + } + } else { + map.put("0", Hex.toHexString(data)); + } + } catch (UnsupportedOperationException e) { + logger.debug("UnsupportedOperationException", e); + map.clear(); + map.put(startIndex.toString(), Hex.toHexString(data)); + } + return map; + } + + private static boolean topicsMatched(List topicList, JSONObject entry) { + if (topicList == null || topicList.isEmpty()) { + return true; + } + int inputSize = 1; + JSONArray inputs = entry.getJSONArray(INPUTS); + for (int i = 0; i < inputs.size(); i++) { + JSONObject param = inputs.getJSONObject(i); + Boolean indexed = param.getBoolean(INDEXED); + if (indexed != null && indexed) { + inputSize++; + } + } + return inputSize == topicList.size(); + } + +} diff --git a/src/main/java/org/tron/common/logsfilter/EventPluginConfig.java b/src/main/java/org/tron/common/logsfilter/EventPluginConfig.java index fcb21dad2f6..5656b7d5c44 100644 --- a/src/main/java/org/tron/common/logsfilter/EventPluginConfig.java +++ b/src/main/java/org/tron/common/logsfilter/EventPluginConfig.java @@ -24,6 +24,18 @@ public class EventPluginConfig { @Setter private String dbConfig; + @Getter + @Setter + private boolean useNativeQueue; + + @Getter + @Setter + private int bindPort; + + @Getter + @Setter + private int sendQueueLength; + @Getter @Setter @@ -33,6 +45,9 @@ public EventPluginConfig() { pluginPath = ""; serverAddress = ""; dbConfig = ""; + useNativeQueue = false; + bindPort = 0; + sendQueueLength = 0; triggerConfigList = new ArrayList<>(); } } diff --git a/src/main/java/org/tron/common/logsfilter/EventPluginLoader.java b/src/main/java/org/tron/common/logsfilter/EventPluginLoader.java index 28c6a219514..8dd617cd6f3 100644 --- a/src/main/java/org/tron/common/logsfilter/EventPluginLoader.java +++ b/src/main/java/org/tron/common/logsfilter/EventPluginLoader.java @@ -11,12 +11,12 @@ import org.pf4j.ManifestPluginDescriptorFinder; import org.pf4j.PluginManager; import org.springframework.util.StringUtils; +import org.tron.common.logsfilter.nativequeue.NativeMessageQueue; import org.tron.common.logsfilter.trigger.BlockLogTrigger; import org.tron.common.logsfilter.trigger.ContractEventTrigger; import org.tron.common.logsfilter.trigger.ContractLogTrigger; import org.tron.common.logsfilter.trigger.TransactionLogTrigger; import org.tron.common.logsfilter.trigger.Trigger; -import org.tron.common.utils.StringUtil; @Slf4j public class EventPluginLoader { @@ -45,6 +45,8 @@ public class EventPluginLoader { private FilterQuery filterQuery; + private boolean useNativeQueue = false; + public static EventPluginLoader getInstance() { if (Objects.isNull(instance)) { synchronized (EventPluginLoader.class) { @@ -56,17 +58,29 @@ public static EventPluginLoader getInstance() { return instance; } - public boolean start(EventPluginConfig config) { - boolean success = false; + private boolean launchNativeQueue(EventPluginConfig config){ - if (Objects.isNull(config)) { - return success; + if (!NativeMessageQueue.getInstance().start(config.getBindPort(), config.getSendQueueLength())){ + return false; } + if (Objects.isNull(triggerConfigList)){ + logger.error("trigger config is null"); + return false; + } + + triggerConfigList.forEach(triggerConfig -> { + setSingleTriggerConfig(triggerConfig); + }); + + return true; + } + + private boolean launchEventPlugin(EventPluginConfig config){ + boolean success = false; // parsing subscribe config from config.conf String pluginPath = config.getPluginPath(); this.serverAddress = config.getServerAddress(); - this.triggerConfigList = config.getTriggerConfigList(); this.dbConfig = config.getDbConfig(); if (!startPlugin(pluginPath)) { @@ -83,6 +97,24 @@ public boolean start(EventPluginConfig config) { return true; } + public boolean start(EventPluginConfig config) { + boolean success = false; + + if (Objects.isNull(config)) { + return success; + } + + this.triggerConfigList = config.getTriggerConfigList(); + + useNativeQueue = config.isUseNativeQueue(); + + if (config.isUseNativeQueue()){ + return launchNativeQueue(config); + } + + return launchEventPlugin(config); + } + private void setPluginConfig() { if (Objects.isNull(eventListeners)) { @@ -96,39 +128,58 @@ private void setPluginConfig() { eventListeners.forEach(listener -> listener.setDBConfig(this.dbConfig)); triggerConfigList.forEach(triggerConfig -> { - if (EventPluginConfig.BLOCK_TRIGGER_NAME.equalsIgnoreCase(triggerConfig.getTriggerName())) { - if (triggerConfig.isEnabled()) { - blockLogTriggerEnable = true; - } else { - blockLogTriggerEnable = false; - } + setSingleTriggerConfig(triggerConfig); + }); + } + + private void setSingleTriggerConfig(TriggerConfig triggerConfig){ + if (EventPluginConfig.BLOCK_TRIGGER_NAME.equalsIgnoreCase(triggerConfig.getTriggerName())) { + if (triggerConfig.isEnabled()) { + blockLogTriggerEnable = true; + } else { + blockLogTriggerEnable = false; + } + + if (!useNativeQueue){ setPluginTopic(Trigger.BLOCK_TRIGGER, triggerConfig.getTopic()); - } else if (EventPluginConfig.TRANSACTION_TRIGGER_NAME - .equalsIgnoreCase(triggerConfig.getTriggerName())) { - if (triggerConfig.isEnabled()) { - transactionLogTriggerEnable = true; - } else { - transactionLogTriggerEnable = false; - } + } + + } else if (EventPluginConfig.TRANSACTION_TRIGGER_NAME + .equalsIgnoreCase(triggerConfig.getTriggerName())) { + if (triggerConfig.isEnabled()) { + transactionLogTriggerEnable = true; + } else { + transactionLogTriggerEnable = false; + } + + if (!useNativeQueue){ setPluginTopic(Trigger.TRANSACTION_TRIGGER, triggerConfig.getTopic()); - } else if (EventPluginConfig.CONTRACTEVENT_TRIGGER_NAME - .equalsIgnoreCase(triggerConfig.getTriggerName())) { - if (triggerConfig.isEnabled()) { - contractEventTriggerEnable = true; - } else { - contractEventTriggerEnable = false; - } + } + + } else if (EventPluginConfig.CONTRACTEVENT_TRIGGER_NAME + .equalsIgnoreCase(triggerConfig.getTriggerName())) { + if (triggerConfig.isEnabled()) { + contractEventTriggerEnable = true; + } else { + contractEventTriggerEnable = false; + } + + if (!useNativeQueue){ setPluginTopic(Trigger.CONTRACTEVENT_TRIGGER, triggerConfig.getTopic()); - } else if (EventPluginConfig.CONTRACTLOG_TRIGGER_NAME - .equalsIgnoreCase(triggerConfig.getTriggerName())) { - if (triggerConfig.isEnabled()) { - contractLogTriggerEnable = true; - } else { - contractLogTriggerEnable = false; - } + } + + } else if (EventPluginConfig.CONTRACTLOG_TRIGGER_NAME + .equalsIgnoreCase(triggerConfig.getTriggerName())) { + if (triggerConfig.isEnabled()) { + contractLogTriggerEnable = true; + } else { + contractLogTriggerEnable = false; + } + + if (!useNativeQueue){ setPluginTopic(Trigger.CONTRACTLOG_TRIGGER, triggerConfig.getTopic()); } - }); + } } public synchronized boolean isBlockLogTriggerEnable() { @@ -195,32 +246,52 @@ protected CompoundPluginDescriptorFinder createPluginDescriptorFinder() { } public void stopPlugin() { - if (Objects.isNull(pluginManager)) { - logger.info("pluginManager is null"); - return; + if (Objects.nonNull(pluginManager)){ + pluginManager.stopPlugins(); } - pluginManager.stopPlugins(); + NativeMessageQueue.getInstance().stop(); + logger.info("eventPlugin stopped"); } public void postBlockTrigger(BlockLogTrigger trigger) { - eventListeners.forEach(listener -> - listener.handleBlockEvent(toJsonString(trigger))); + if (useNativeQueue){ + NativeMessageQueue.getInstance().publishTrigger(toJsonString(trigger), trigger.getTriggerName()); + } + else { + eventListeners.forEach(listener -> + listener.handleBlockEvent(toJsonString(trigger))); + } } public void postTransactionTrigger(TransactionLogTrigger trigger) { - eventListeners.forEach(listener -> listener.handleTransactionTrigger(toJsonString(trigger))); + if (useNativeQueue){ + NativeMessageQueue.getInstance().publishTrigger(toJsonString(trigger), trigger.getTriggerName()); + } + else { + eventListeners.forEach(listener -> listener.handleTransactionTrigger(toJsonString(trigger))); + } } public void postContractLogTrigger(ContractLogTrigger trigger) { - eventListeners.forEach(listener -> - listener.handleContractLogTrigger(toJsonString(trigger))); + if (useNativeQueue){ + NativeMessageQueue.getInstance().publishTrigger(toJsonString(trigger), trigger.getTriggerName()); + } + else { + eventListeners.forEach(listener -> + listener.handleContractLogTrigger(toJsonString(trigger))); + } } public void postContractEventTrigger(ContractEventTrigger trigger) { - eventListeners.forEach(listener -> - listener.handleContractEventTrigger(toJsonString(trigger))); + if (useNativeQueue){ + NativeMessageQueue.getInstance().publishTrigger(toJsonString(trigger), trigger.getTriggerName()); + } + else { + eventListeners.forEach(listener -> + listener.handleContractEventTrigger(toJsonString(trigger))); + } } private String toJsonString(Object data) { @@ -242,6 +313,4 @@ public synchronized void setFilterQuery(FilterQuery filterQuery) { public synchronized FilterQuery getFilterQuery() { return filterQuery; } - - } diff --git a/src/main/java/org/tron/common/logsfilter/IPluginEventListener.java b/src/main/java/org/tron/common/logsfilter/IPluginEventListener.java index 8cd70d1c3a2..cd68f59d9ac 100644 --- a/src/main/java/org/tron/common/logsfilter/IPluginEventListener.java +++ b/src/main/java/org/tron/common/logsfilter/IPluginEventListener.java @@ -4,21 +4,21 @@ public interface IPluginEventListener extends ExtensionPoint { - public void setServerAddress(String address); + void setServerAddress(String address); - public void setTopic(int eventType, String topic); + void setTopic(int eventType, String topic); - public void setDBConfig(String dbConfig); + void setDBConfig(String dbConfig); // start should be called after setServerAddress, setTopic, setDBConfig - public void start(); + void start(); - public void handleBlockEvent(Object trigger); + void handleBlockEvent(Object trigger); - public void handleTransactionTrigger(Object trigger); + void handleTransactionTrigger(Object trigger); - public void handleContractLogTrigger(Object trigger); + void handleContractLogTrigger(Object trigger); - public void handleContractEventTrigger(Object trigger); + void handleContractEventTrigger(Object trigger); } diff --git a/src/main/java/org/tron/common/logsfilter/capsule/ContractEventTriggerCapsule.java b/src/main/java/org/tron/common/logsfilter/capsule/ContractEventTriggerCapsule.java index 76f6bd8b2d1..e2a37d52a20 100644 --- a/src/main/java/org/tron/common/logsfilter/capsule/ContractEventTriggerCapsule.java +++ b/src/main/java/org/tron/common/logsfilter/capsule/ContractEventTriggerCapsule.java @@ -3,7 +3,7 @@ import java.util.List; import lombok.Getter; import lombok.Setter; -import org.tron.common.logsfilter.ContractEventParser; +import org.tron.common.logsfilter.ContractEventParserAbi; import org.tron.common.logsfilter.EventPluginLoader; import org.tron.common.logsfilter.FilterQuery; import org.tron.common.logsfilter.trigger.ContractEventTrigger; @@ -54,8 +54,9 @@ public ContractEventTriggerCapsule(LogEventWrapper log) { @Override public void processTrigger() { - contractEventTrigger.setTopicMap(ContractEventParser.parseTopics(topicList, abiEntry)); - contractEventTrigger.setDataMap(ContractEventParser.parseEventData(data, topicList, abiEntry)); + contractEventTrigger.setTopicMap(ContractEventParserAbi.parseTopics(topicList, abiEntry)); + contractEventTrigger + .setDataMap(ContractEventParserAbi.parseEventData(data, topicList, abiEntry)); if (FilterQuery.matchFilter(contractEventTrigger)) { EventPluginLoader.getInstance().postContractEventTrigger(contractEventTrigger); diff --git a/src/main/java/org/tron/common/logsfilter/capsule/ContractTriggerCapsule.java b/src/main/java/org/tron/common/logsfilter/capsule/ContractTriggerCapsule.java new file mode 100644 index 00000000000..a17d41930be --- /dev/null +++ b/src/main/java/org/tron/common/logsfilter/capsule/ContractTriggerCapsule.java @@ -0,0 +1,157 @@ +package org.tron.common.logsfilter.capsule; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import java.util.List; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.ArrayUtils; +import org.pf4j.util.StringUtils; +import org.spongycastle.util.encoders.Hex; +import org.tron.common.crypto.Hash; +import org.tron.common.logsfilter.ContractEventParserJson; +import org.tron.common.logsfilter.EventPluginLoader; +import org.tron.common.logsfilter.FilterQuery; +import org.tron.common.logsfilter.trigger.ContractEventTrigger; +import org.tron.common.logsfilter.trigger.ContractLogTrigger; +import org.tron.common.logsfilter.trigger.ContractTrigger; +import org.tron.common.runtime.vm.DataWord; +import org.tron.common.runtime.vm.LogInfo; +import org.tron.core.config.args.Args; + +public class ContractTriggerCapsule extends TriggerCapsule { + + @Getter + @Setter + private ContractTrigger contractTrigger; + + public ContractTriggerCapsule(ContractTrigger contractTrigger) { + this.contractTrigger = contractTrigger; + } + + public void setLatestSolidifiedBlockNumber(long latestSolidifiedBlockNumber) { + contractTrigger.setLatestSolidifiedBlockNumber(latestSolidifiedBlockNumber); + } + + @Override + public void processTrigger() { + ContractTrigger event; + boolean isEvent = false; + LogInfo logInfo = contractTrigger.getLogInfo(); + JSONObject abi = null; + JSONArray entrys = null; + String abiString = contractTrigger.getAbiString(); + + Object abiObj = JSON.parse(abiString); + if (abiObj instanceof JSONObject) { + abi = (JSONObject) abiObj; + entrys = abi.getJSONArray("entrys"); + } + + List topics = logInfo.getTopics(); + + String eventSignature = ""; + String eventSignatureFull = "fallback()"; + String entryName = ""; + JSONObject entryObj = new JSONObject(); + + if (entrys != null && topics != null && !topics.isEmpty() && !ArrayUtils + .isEmpty(topics.get(0).getData()) && Args.getInstance().getStorage() + .isContractParseSwitch()) { + String logHash = topics.get(0).toString(); + for (int i = 0; i < entrys.size(); i++) { + JSONObject entry = entrys.getJSONObject(i); + + String funcType = entry.getString("type"); + Boolean anonymous = entry.getBoolean("anonymous"); + if (funcType == null || !"event".equalsIgnoreCase(funcType)) { + continue; + } + + if (anonymous != null && anonymous) { + continue; + } + + String signature = entry.getString("name") + "("; + String signatureFull = entry.getString("name") + "("; + StringBuilder signBuilder = new StringBuilder(); + StringBuilder signFullBuilder = new StringBuilder(); + JSONArray inputs = entry.getJSONArray("inputs"); + if (inputs != null) { + for (int j = 0; j < inputs.size(); j++) { + if (signBuilder.length() > 0) { + signBuilder.append(","); + signFullBuilder.append(","); + } + String type = inputs.getJSONObject(j).getString("type"); + String name = inputs.getJSONObject(j).getString("name"); + signBuilder.append(type); + signFullBuilder.append(type); + if (StringUtils.isNotNullOrEmpty(name)) { + signFullBuilder.append(" ").append(name); + } + } + } + signature += signBuilder.toString() + ")"; + signatureFull += signFullBuilder.toString() + ")"; + String sha3 = Hex.toHexString(Hash.sha3(signature.getBytes())); + if (sha3.equals(logHash)) { + eventSignature = signature; + eventSignatureFull = signatureFull; + entryName = entry.getString("name"); + entryObj = entry; + isEvent = true; + break; + } + } + } + + if (isEvent) { + if (!EventPluginLoader.getInstance().isContractEventTriggerEnable()) { + return; + } + event = new ContractEventTrigger(); + ((ContractEventTrigger) event).setEventSignature(eventSignature); + ((ContractEventTrigger) event).setEventSignatureFull(eventSignatureFull); + ((ContractEventTrigger) event).setEventName(entryName); + + List topicList = logInfo.getClonedTopics(); + byte[] data = logInfo.getClonedData(); + + ((ContractEventTrigger) event) + .setTopicMap(ContractEventParserJson.parseTopics(topicList, entryObj)); + ((ContractEventTrigger) event) + .setDataMap(ContractEventParserJson.parseEventData(data, topicList, entryObj)); + } else { + if (!EventPluginLoader.getInstance().isContractLogTriggerEnable()) { + return; + } + event = new ContractLogTrigger(); + ((ContractLogTrigger) event).setTopicList(logInfo.getHexTopics()); + ((ContractLogTrigger) event).setData(logInfo.getHexData()); + } + + RawData rawData = new RawData(logInfo.getAddress(), logInfo.getTopics(), logInfo.getData()); + + event.setRawData(rawData); + event.setAbiString(contractTrigger.getAbiString()); + + event.setUniqueId(contractTrigger.getUniqueId()); + event.setTransactionId(contractTrigger.getTransactionId()); + event.setContractAddress(contractTrigger.getContractAddress()); + event.setOriginAddress(contractTrigger.getOriginAddress()); + event.setCallerAddress(""); + event.setCreatorAddress(contractTrigger.getCreatorAddress()); + event.setBlockNumber(contractTrigger.getBlockNumber()); + event.setTimeStamp(contractTrigger.getTimeStamp()); + + if (FilterQuery.matchFilter(contractTrigger)) { + if (isEvent) { + EventPluginLoader.getInstance().postContractEventTrigger((ContractEventTrigger) event); + } else { + EventPluginLoader.getInstance().postContractLogTrigger((ContractLogTrigger) event); + } + } + } +} diff --git a/src/main/java/org/tron/common/logsfilter/capsule/RawData.java b/src/main/java/org/tron/common/logsfilter/capsule/RawData.java new file mode 100644 index 00000000000..c226fe37748 --- /dev/null +++ b/src/main/java/org/tron/common/logsfilter/capsule/RawData.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.tron.common.logsfilter.capsule; + +import java.util.ArrayList; +import java.util.List; +import lombok.Data; +import lombok.Getter; +import org.spongycastle.util.encoders.Hex; +import org.tron.common.runtime.vm.DataWord; + +@Data +public class RawData { + + // for mongodb + @Getter + private String address; + @Getter + private List topics; + @Getter + private String data; + + public RawData(byte[] address, List topics, byte[] data) { + this.address = (address != null) ? Hex.toHexString(address) : ""; + this.topics = (address != null) ? topics : new ArrayList<>(); + this.data = (data != null) ? Hex.toHexString(data) : ""; + } +} diff --git a/src/main/java/org/tron/common/logsfilter/capsule/TransactionLogTriggerCapsule.java b/src/main/java/org/tron/common/logsfilter/capsule/TransactionLogTriggerCapsule.java index 61cea320431..c91c3074ce8 100644 --- a/src/main/java/org/tron/common/logsfilter/capsule/TransactionLogTriggerCapsule.java +++ b/src/main/java/org/tron/common/logsfilter/capsule/TransactionLogTriggerCapsule.java @@ -132,8 +132,8 @@ public TransactionLogTriggerCapsule(TransactionCapsule trxCasule, BlockCapsule b } // program result - ProgramResult programResult = trxTrace.getRuntime().getResult(); - if (Objects.nonNull(trxTrace) && Objects.nonNull(programResult)) { + if (Objects.nonNull(trxTrace) && Objects.nonNull(trxTrace.getRuntime()) && Objects.nonNull(trxTrace.getRuntime().getResult())) { + ProgramResult programResult = trxTrace.getRuntime().getResult(); ByteString contractResult = ByteString.copyFrom(programResult.getHReturn()); ByteString contractAddress = ByteString.copyFrom(programResult.getContractAddress()); diff --git a/src/main/java/org/tron/common/logsfilter/nativequeue/NativeMessageQueue.java b/src/main/java/org/tron/common/logsfilter/nativequeue/NativeMessageQueue.java new file mode 100644 index 00000000000..ec0a1ce624f --- /dev/null +++ b/src/main/java/org/tron/common/logsfilter/nativequeue/NativeMessageQueue.java @@ -0,0 +1,65 @@ +package org.tron.common.logsfilter.nativequeue; + +import org.zeromq.SocketType; +import org.zeromq.ZContext; +import org.zeromq.ZMQ; +import java.util.Objects; + +public class NativeMessageQueue { + ZContext context = null; + private ZMQ.Socket publisher = null; + private static NativeMessageQueue instance; + private static final int DEFAULT_BIND_PORT = 5555; + private static final int DEFAULT_QUEUE_LENGTH = 1000; + public static NativeMessageQueue getInstance() { + if (Objects.isNull(instance)) { + synchronized (NativeMessageQueue.class) { + if (Objects.isNull(instance)) { + instance = new NativeMessageQueue(); + } + } + } + return instance; + } + + public boolean start(int bindPort, int sendQueueLength) { + context = new ZContext(); + publisher = context.createSocket(SocketType.PUB); + + if (Objects.isNull(publisher)){ + return false; + } + + if (bindPort == 0 || bindPort < 0) { + bindPort = DEFAULT_BIND_PORT; + } + + if (sendQueueLength < 0){ + sendQueueLength = DEFAULT_QUEUE_LENGTH; + } + + context.setSndHWM(sendQueueLength); + + String bindAddress = String.format("tcp://*:%d", bindPort); + return publisher.bind(bindAddress); + } + + public void stop(){ + if (Objects.nonNull(publisher)){ + publisher.close(); + } + + if (Objects.nonNull(context)){ + context.close(); + } + } + + public void publishTrigger(String data, String topic){ + if (Objects.isNull(publisher) || Objects.isNull(context.isClosed()) || context.isClosed()) { + return; + } + + publisher.sendMore(topic); + publisher.send(data); + } +} diff --git a/src/main/java/org/tron/common/logsfilter/trigger/ContractEventTrigger.java b/src/main/java/org/tron/common/logsfilter/trigger/ContractEventTrigger.java index 3f6355cf183..72c5ce5231e 100644 --- a/src/main/java/org/tron/common/logsfilter/trigger/ContractEventTrigger.java +++ b/src/main/java/org/tron/common/logsfilter/trigger/ContractEventTrigger.java @@ -23,7 +23,7 @@ public class ContractEventTrigger extends ContractTrigger { /** * decode from topicList with the ABI of this contract. this item is null if not called - * ContractEventParser::parseTopics(ContractEventTrigger trigger) + * ContractEventParserAbi::parseTopics(ContractEventTrigger trigger) */ @Getter @Setter @@ -31,7 +31,7 @@ public class ContractEventTrigger extends ContractTrigger { /** * multi data items will be concat into a single string. this item is null if not called - * ContractEventParser::parseData(ContractEventTrigger trigger) + * ContractEventParserAbi::parseData(ContractEventTrigger trigger) */ @Getter @Setter diff --git a/src/main/java/org/tron/common/logsfilter/trigger/ContractTrigger.java b/src/main/java/org/tron/common/logsfilter/trigger/ContractTrigger.java index e573be11ded..3780c49e5ef 100644 --- a/src/main/java/org/tron/common/logsfilter/trigger/ContractTrigger.java +++ b/src/main/java/org/tron/common/logsfilter/trigger/ContractTrigger.java @@ -2,6 +2,8 @@ import lombok.Getter; import lombok.Setter; +import org.tron.common.logsfilter.capsule.RawData; +import org.tron.common.runtime.vm.LogInfo; public class ContractTrigger extends Trigger { @@ -64,4 +66,16 @@ public class ContractTrigger extends Trigger { @Getter @Setter private long latestSolidifiedBlockNumber; + + @Getter + @Setter + private LogInfo logInfo; + + @Getter + @Setter + private RawData rawData; + + @Getter + @Setter + private String abiString; } diff --git a/src/main/java/org/tron/common/net/udp/message/Message.java b/src/main/java/org/tron/common/net/udp/message/Message.java index 0d272cf65d1..2e5eff8a982 100644 --- a/src/main/java/org/tron/common/net/udp/message/Message.java +++ b/src/main/java/org/tron/common/net/udp/message/Message.java @@ -40,6 +40,8 @@ public Sha256Hash getMessageId() { public abstract Node getFrom(); + public abstract long getTimestamp(); + @Override public String toString() { return "[Message Type: " + getType() + ", len: " + (data == null ? 0 : data.length) + "]"; diff --git a/src/main/java/org/tron/common/net/udp/message/backup/KeepAliveMessage.java b/src/main/java/org/tron/common/net/udp/message/backup/KeepAliveMessage.java index 9f9d63540a1..7e3ed37684a 100644 --- a/src/main/java/org/tron/common/net/udp/message/backup/KeepAliveMessage.java +++ b/src/main/java/org/tron/common/net/udp/message/backup/KeepAliveMessage.java @@ -29,6 +29,11 @@ public int getPriority() { return backupMessage.getPriority(); } + @Override + public long getTimestamp() { + return 0; + } + @Override public Node getFrom() { return null; diff --git a/src/main/java/org/tron/common/net/udp/message/discover/FindNodeMessage.java b/src/main/java/org/tron/common/net/udp/message/discover/FindNodeMessage.java index a287a9681f6..1507366a9c5 100755 --- a/src/main/java/org/tron/common/net/udp/message/discover/FindNodeMessage.java +++ b/src/main/java/org/tron/common/net/udp/message/discover/FindNodeMessage.java @@ -38,6 +38,11 @@ public byte[] getTargetId() { return this.findNeighbours.getTargetId().toByteArray(); } + @Override + public long getTimestamp() { + return this.findNeighbours.getTimestamp(); + } + @Override public Node getFrom() { return Message.getNode(findNeighbours.getFrom()); diff --git a/src/main/java/org/tron/common/net/udp/message/discover/NeighborsMessage.java b/src/main/java/org/tron/common/net/udp/message/discover/NeighborsMessage.java index 8e561aa0238..61f7bddd18e 100755 --- a/src/main/java/org/tron/common/net/udp/message/discover/NeighborsMessage.java +++ b/src/main/java/org/tron/common/net/udp/message/discover/NeighborsMessage.java @@ -22,10 +22,10 @@ public NeighborsMessage(byte[] data) throws Exception { this.neighbours = Discover.Neighbours.parseFrom(data); } - public NeighborsMessage(Node from, List neighbours) { + public NeighborsMessage(Node from, List neighbours, long sequence) { super(DISCOVER_NEIGHBORS, null); Builder builder = Neighbours.newBuilder() - .setTimestamp(System.currentTimeMillis()); + .setTimestamp(sequence); neighbours.forEach(neighbour -> { Endpoint endpoint = Endpoint.newBuilder() @@ -59,6 +59,11 @@ public List getNodes() { return nodes; } + @Override + public long getTimestamp() { + return this.neighbours.getTimestamp(); + } + @Override public Node getFrom() { return Message.getNode(neighbours.getFrom()); diff --git a/src/main/java/org/tron/common/net/udp/message/discover/PingMessage.java b/src/main/java/org/tron/common/net/udp/message/discover/PingMessage.java index a0185485477..e7510414163 100755 --- a/src/main/java/org/tron/common/net/udp/message/discover/PingMessage.java +++ b/src/main/java/org/tron/common/net/udp/message/discover/PingMessage.java @@ -51,6 +51,11 @@ public Node getTo() { return node; } + @Override + public long getTimestamp() { + return this.pingMessage.getTimestamp(); + } + @Override public Node getFrom() { return Message.getNode(pingMessage.getFrom()); diff --git a/src/main/java/org/tron/common/net/udp/message/discover/PongMessage.java b/src/main/java/org/tron/common/net/udp/message/discover/PongMessage.java index dfd19760a8b..64b20eb32c7 100755 --- a/src/main/java/org/tron/common/net/udp/message/discover/PongMessage.java +++ b/src/main/java/org/tron/common/net/udp/message/discover/PongMessage.java @@ -19,7 +19,7 @@ public PongMessage(byte[] data) throws Exception { this.pongMessage = Discover.PongMessage.parseFrom(data); } - public PongMessage(Node from) { + public PongMessage(Node from, long sequence) { super(DISCOVER_PONG, null); Endpoint toEndpoint = Endpoint.newBuilder() .setAddress(ByteString.copyFrom(ByteArray.fromString(from.getHost()))) @@ -29,7 +29,7 @@ public PongMessage(Node from) { this.pongMessage = Discover.PongMessage.newBuilder() .setFrom(toEndpoint) .setEcho(Args.getInstance().getNodeP2pVersion()) - .setTimestamp(System.currentTimeMillis()) + .setTimestamp(sequence) .build(); this.data = this.pongMessage.toByteArray(); } @@ -38,6 +38,11 @@ public int getVersion() { return this.pongMessage.getEcho(); } + @Override + public long getTimestamp() { + return this.pongMessage.getTimestamp(); + } + @Override public Node getFrom() { return Message.getNode(pongMessage.getFrom()); diff --git a/src/main/java/org/tron/common/overlay/client/PeerClient.java b/src/main/java/org/tron/common/overlay/client/PeerClient.java index c264938fbc7..bdd5eb7606e 100644 --- a/src/main/java/org/tron/common/overlay/client/PeerClient.java +++ b/src/main/java/org/tron/common/overlay/client/PeerClient.java @@ -31,7 +31,7 @@ public class PeerClient { public PeerClient() { workerGroup = new NioEventLoopGroup(0, new ThreadFactory() { - AtomicInteger cnt = new AtomicInteger(0); + private AtomicInteger cnt = new AtomicInteger(0); @Override public Thread newThread(Runnable r) { diff --git a/src/main/java/org/tron/common/overlay/discover/DiscoverServer.java b/src/main/java/org/tron/common/overlay/discover/DiscoverServer.java index 9ec5330abc9..66c44674461 100755 --- a/src/main/java/org/tron/common/overlay/discover/DiscoverServer.java +++ b/src/main/java/org/tron/common/overlay/discover/DiscoverServer.java @@ -18,6 +18,7 @@ package org.tron.common.overlay.discover; +import com.sun.org.apache.xpath.internal.Arg; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelInitializer; @@ -58,7 +59,7 @@ public class DiscoverServer { @Autowired public DiscoverServer(final NodeManager nodeManager) { this.nodeManager = nodeManager; - if (args.isNodeDiscoveryEnable()) { + if (args.isNodeDiscoveryEnable() && !args.isFastForward()) { if (port == 0) { logger.error("Discovery can't be started while listen port == 0"); } else { @@ -66,8 +67,7 @@ public DiscoverServer(final NodeManager nodeManager) { try { start(); } catch (Exception e) { - logger.debug(e.getMessage(), e); - throw new RuntimeException(e); + logger.error("Discovery server start failed.", e); } }, "DiscoverServer").start(); } diff --git a/src/main/java/org/tron/common/overlay/discover/DiscoverTask.java b/src/main/java/org/tron/common/overlay/discover/DiscoverTask.java index 5a7262e035e..f3d7690d967 100644 --- a/src/main/java/org/tron/common/overlay/discover/DiscoverTask.java +++ b/src/main/java/org/tron/common/overlay/discover/DiscoverTask.java @@ -40,7 +40,7 @@ public DiscoverTask(NodeManager nodeManager) { @Override public void run() { - discover(nodeId, 0, new ArrayList()); + discover(nodeId, 0, new ArrayList<>()); } public synchronized void discover(byte[] nodeId, int round, List prevTried) { @@ -64,7 +64,6 @@ public synchronized void discover(byte[] nodeId, int round, List prevTried nodeManager.getNodeHandler(n).sendFindNode(nodeId); tried.add(n); wait(50); - } catch (InterruptedException e) { } catch (Exception ex) { logger.error("Unexpected Exception " + ex, ex); } diff --git a/src/main/java/org/tron/common/overlay/discover/RefreshTask.java b/src/main/java/org/tron/common/overlay/discover/RefreshTask.java index e81c7ae82b9..02516d1d893 100644 --- a/src/main/java/org/tron/common/overlay/discover/RefreshTask.java +++ b/src/main/java/org/tron/common/overlay/discover/RefreshTask.java @@ -20,9 +20,11 @@ import java.util.ArrayList; import java.util.Random; +import lombok.extern.slf4j.Slf4j; import org.tron.common.overlay.discover.node.Node; import org.tron.common.overlay.discover.node.NodeManager; +@Slf4j(topic = "discover") public class RefreshTask extends DiscoverTask { public RefreshTask(NodeManager nodeManager) { diff --git a/src/main/java/org/tron/common/overlay/discover/node/Node.java b/src/main/java/org/tron/common/overlay/discover/node/Node.java index 423e07ce5db..685ca0e780a 100644 --- a/src/main/java/org/tron/common/overlay/discover/node/Node.java +++ b/src/main/java/org/tron/common/overlay/discover/node/Node.java @@ -54,7 +54,7 @@ public void setReputation(int reputation) { public static Node instanceOf(String addressOrEnode) { try { URI uri = new URI(addressOrEnode); - if (uri.getScheme().equals("enode")) { + if ("enode".equals(uri.getScheme())) { return new Node(addressOrEnode); } } catch (URISyntaxException e) { @@ -78,7 +78,7 @@ public String getEnodeURL() { public Node(String enodeURL) { try { URI uri = new URI(enodeURL); - if (!uri.getScheme().equals("enode")) { + if (!"enode".equals(uri.getScheme())) { throw new RuntimeException("expecting URL in the format enode://PUBKEY@HOST:PORT"); } this.id = Hex.decode(uri.getUserInfo()); diff --git a/src/main/java/org/tron/common/overlay/discover/node/NodeHandler.java b/src/main/java/org/tron/common/overlay/discover/node/NodeHandler.java index a4fb678d19d..fece3822772 100644 --- a/src/main/java/org/tron/common/overlay/discover/node/NodeHandler.java +++ b/src/main/java/org/tron/common/overlay/discover/node/NodeHandler.java @@ -21,6 +21,7 @@ import java.net.InetSocketAddress; import java.util.List; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; import lombok.extern.slf4j.Slf4j; import org.tron.common.net.udp.handler.UdpEvent; import org.tron.common.net.udp.message.Message; @@ -83,10 +84,12 @@ public enum State { private NodeStatistics nodeStatistics; private NodeHandler replaceCandidate; private InetSocketAddress inetSocketAddress; + private AtomicInteger pingTrials = new AtomicInteger(3); private volatile boolean waitForPong = false; private volatile boolean waitForNeighbors = false; - private volatile int pingTrials = 3; - private long pingSent; + private volatile long pingSent; + private volatile long pingSequence; + private volatile long findnodeSequence; public NodeHandler(Node node, NodeManager nodeManager) { this.node = node; @@ -186,7 +189,7 @@ public void changeState(State newState) { public void handlePing(PingMessage msg) { if (!nodeManager.getTable().getNode().equals(node)) { - sendPong(); + sendPong(msg.getTimestamp()); } if (msg.getVersion() != Args.getInstance().getNodeP2pVersion()) { changeState(State.NonActive); @@ -225,12 +228,12 @@ public void handleNeighbours(NeighborsMessage msg) { public void handleFindNode(FindNodeMessage msg) { List closest = nodeManager.getTable().getClosestNodes(msg.getTargetId()); - sendNeighbours(closest); + sendNeighbours(closest, msg.getTimestamp()); } public void handleTimedOut() { waitForPong = false; - if (--pingTrials > 0) { + if (pingTrials.getAndDecrement() > 0) { sendPing(); } else { if (state == State.Discovered) { @@ -244,10 +247,11 @@ public void handleTimedOut() { } public void sendPing() { - Message ping = new PingMessage(nodeManager.getPublicHomeNode(), getNode()); + PingMessage msg = new PingMessage(nodeManager.getPublicHomeNode(), getNode()); + pingSequence = msg.getTimestamp(); waitForPong = true; pingSent = System.currentTimeMillis(); - sendMessage(ping); + sendMessage(msg); if (nodeManager.getPongTimer().isShutdown()) { return; @@ -264,20 +268,21 @@ public void sendPing() { }, PingTimeout, TimeUnit.MILLISECONDS); } - public void sendPong() { - Message pong = new PongMessage(nodeManager.getPublicHomeNode()); + public void sendPong(long sequence) { + Message pong = new PongMessage(nodeManager.getPublicHomeNode(), sequence); sendMessage(pong); } - public void sendNeighbours(List neighbours) { - Message neighbors = new NeighborsMessage(nodeManager.getPublicHomeNode(), neighbours); - sendMessage(neighbors); - } - public void sendFindNode(byte[] target) { waitForNeighbors = true; - Message findNode = new FindNodeMessage(nodeManager.getPublicHomeNode(), target); - sendMessage(findNode); + FindNodeMessage msg = new FindNodeMessage(nodeManager.getPublicHomeNode(), target); + findnodeSequence = msg.getTimestamp(); + sendMessage(msg); + } + + public void sendNeighbours(List neighbours, long sequence) { + Message msg = new NeighborsMessage(nodeManager.getPublicHomeNode(), neighbours, sequence); + sendMessage(msg); } private void sendMessage(Message msg) { diff --git a/src/main/java/org/tron/common/overlay/discover/node/statistics/NodeStatistics.java b/src/main/java/org/tron/common/overlay/discover/node/statistics/NodeStatistics.java index 2923579d93e..5b859658bc0 100644 --- a/src/main/java/org/tron/common/overlay/discover/node/statistics/NodeStatistics.java +++ b/src/main/java/org/tron/common/overlay/discover/node/statistics/NodeStatistics.java @@ -18,6 +18,7 @@ package org.tron.common.overlay.discover.node.statistics; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import lombok.Getter; import org.tron.common.overlay.discover.node.Node; @@ -185,7 +186,7 @@ public class SimpleStatter { private final String name; private volatile double last; private volatile double sum; - private volatile int count; + private AtomicInteger count = new AtomicInteger(); public SimpleStatter(String name) { this.name = name; @@ -194,7 +195,7 @@ public SimpleStatter(String name) { public void add(double value) { last = value; sum += value; - count++; + count.incrementAndGet(); } public double getLast() { @@ -202,7 +203,7 @@ public double getLast() { } public int getCount() { - return count; + return count.get(); } public double getSum() { @@ -210,7 +211,7 @@ public double getSum() { } public double getAvrg() { - return count == 0 ? 0 : sum / count; + return count.get() == 0 ? 0 : sum / count.get(); } public String getName() { diff --git a/src/main/java/org/tron/common/overlay/discover/table/DistanceComparator.java b/src/main/java/org/tron/common/overlay/discover/table/DistanceComparator.java index 55d53ebeaad..7da8cc4683f 100644 --- a/src/main/java/org/tron/common/overlay/discover/table/DistanceComparator.java +++ b/src/main/java/org/tron/common/overlay/discover/table/DistanceComparator.java @@ -24,7 +24,7 @@ */ public class DistanceComparator implements Comparator { - byte[] targetId; + private byte[] targetId; DistanceComparator(byte[] targetId) { this.targetId = targetId; diff --git a/src/main/java/org/tron/common/overlay/discover/table/NodeEntry.java b/src/main/java/org/tron/common/overlay/discover/table/NodeEntry.java index 786fd1c152e..04756144add 100644 --- a/src/main/java/org/tron/common/overlay/discover/table/NodeEntry.java +++ b/src/main/java/org/tron/common/overlay/discover/table/NodeEntry.java @@ -25,7 +25,7 @@ public class NodeEntry { private byte[] ownerId; - Node node; + private Node node; private String entryId; private int distance; private long modified; @@ -84,8 +84,6 @@ public int hashCode() { } public static int distance(byte[] ownerId, byte[] targetId) { -// byte[] h1 = keccak(targetId); -// byte[] h2 = keccak(ownerId); byte[] h1 = targetId; byte[] h2 = ownerId; @@ -103,7 +101,7 @@ public static int distance(byte[] ownerId, byte[] targetId) { } else { int count = 0; for (int i = 7; i >= 0; i--) { - boolean a = (b & (1 << i)) == 0; + boolean a = ((b & 0xff) & (1 << i)) == 0; if (a) { count++; } else { diff --git a/src/main/java/org/tron/common/overlay/discover/table/NodeTable.java b/src/main/java/org/tron/common/overlay/discover/table/NodeTable.java index a4967c0df3c..507d078e3fa 100644 --- a/src/main/java/org/tron/common/overlay/discover/table/NodeTable.java +++ b/src/main/java/org/tron/common/overlay/discover/table/NodeTable.java @@ -32,8 +32,8 @@ public class NodeTable { private final Node node; // our node private transient NodeBucket[] buckets; private transient List nodes; - private Map evictedCandidates = new HashMap<>(); - private Map expectedPongs = new HashMap<>(); +// private Map evictedCandidates = new HashMap<>(); +// private Map expectedPongs = new HashMap<>(); public NodeTable(Node n) { this.node = n; diff --git a/src/main/java/org/tron/common/overlay/message/HelloMessage.java b/src/main/java/org/tron/common/overlay/message/HelloMessage.java index 6d67dba17ac..3342a994e8e 100755 --- a/src/main/java/org/tron/common/overlay/message/HelloMessage.java +++ b/src/main/java/org/tron/common/overlay/message/HelloMessage.java @@ -12,7 +12,7 @@ public class HelloMessage extends P2pMessage { - Protocol.HelloMessage helloMessage; + private Protocol.HelloMessage helloMessage; public HelloMessage(byte type, byte[] rawData) throws Exception { super(type, rawData); diff --git a/src/main/java/org/tron/common/overlay/message/Message.java b/src/main/java/org/tron/common/overlay/message/Message.java index 175d9db16b4..641e24cc54e 100644 --- a/src/main/java/org/tron/common/overlay/message/Message.java +++ b/src/main/java/org/tron/common/overlay/message/Message.java @@ -1,12 +1,20 @@ package org.tron.common.overlay.message; +import static org.tron.core.exception.P2pException.TypeEnum.PROTOBUF_ERROR; + +import com.google.protobuf.CodedInputStream; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; +import java.lang.reflect.Field; import java.util.Arrays; +import lombok.Setter; import org.apache.commons.lang3.ArrayUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.util.ReflectionUtils; import org.tron.common.utils.Sha256Hash; +import org.tron.core.db.Manager; +import org.tron.core.exception.P2pException; import org.tron.core.net.message.MessageTypes; public abstract class Message { @@ -15,6 +23,8 @@ public abstract class Message { protected byte[] data; protected byte type; + @Setter + private static Manager manager; public Message() { } @@ -67,4 +77,30 @@ public boolean equals(Object o) { Message message = (Message) o; return Arrays.equals(data, message.data); } + + public static void compareBytes(byte[] src, byte[] dest) throws P2pException { + if (src.length != dest.length) { + throw new P2pException(PROTOBUF_ERROR, PROTOBUF_ERROR.getDesc()); + } + } + + private static final Field field = ReflectionUtils + .findField(CodedInputStream.class, "explicitDiscardUnknownFields"); + + static { + ReflectionUtils.makeAccessible(field); + } + + public static CodedInputStream getCodedInputStream(byte[] data) { + CodedInputStream codedInputStream = CodedInputStream.newInstance(data); + if (isFilter()) { + ReflectionUtils.setField(field, codedInputStream, true); + } + return codedInputStream; + } + + public static boolean isFilter() { + return manager.getDynamicPropertiesStore().getAllowProtoFilterNum() == 1; + } + } \ No newline at end of file diff --git a/src/main/java/org/tron/common/overlay/message/P2pMessageFactory.java b/src/main/java/org/tron/common/overlay/message/P2pMessageFactory.java index a33c8a0df02..04964c66bd9 100644 --- a/src/main/java/org/tron/common/overlay/message/P2pMessageFactory.java +++ b/src/main/java/org/tron/common/overlay/message/P2pMessageFactory.java @@ -28,8 +28,8 @@ public class P2pMessageFactory extends MessageFactory { @Override public P2pMessage create(byte[] data) throws Exception { if (data.length <= 1) { - throw new P2pException(TypeEnum.MESSAGE_WITH_WRONG_LENGTH, "len=" + data.length - + ", MessageType=" + (data.length == 1 ? data[0] : "unknow")); + throw new P2pException(TypeEnum.MESSAGE_WITH_WRONG_LENGTH, + "messageType=" + (data.length == 1 ? data[0] : "unknow")); } try { byte type = data[0]; @@ -61,8 +61,7 @@ private P2pMessage create(byte type, byte[] rawData) throws Exception { case P2P_PONG: return new PongMessage(type, rawData); default: - throw new P2pException(P2pException.TypeEnum.NO_SUCH_MESSAGE, - messageType.toString() + ", len=" + rawData.length); + throw new P2pException(P2pException.TypeEnum.NO_SUCH_MESSAGE, messageType.toString()); } } } diff --git a/src/main/java/org/tron/common/overlay/server/P2pHandler.java b/src/main/java/org/tron/common/overlay/server/P2pHandler.java index 78a3d6b54bc..e5dae36a51e 100644 --- a/src/main/java/org/tron/common/overlay/server/P2pHandler.java +++ b/src/main/java/org/tron/common/overlay/server/P2pHandler.java @@ -1,20 +1,3 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ package org.tron.common.overlay.server; import static org.tron.common.overlay.message.StaticMessages.PING_MESSAGE; @@ -52,11 +35,8 @@ public class P2pHandler extends SimpleChannelInboundHandler { private volatile long sendPingTime; - private ChannelHandlerContext ctx; - @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { - this.ctx = ctx; pingTask = pingTimer.scheduleAtFixedRate(() -> { if (!hasPing) { sendPingTime = System.currentTimeMillis(); diff --git a/src/main/java/org/tron/common/overlay/server/PeerServer.java b/src/main/java/org/tron/common/overlay/server/PeerServer.java index 78e48235116..8c59ad13e35 100644 --- a/src/main/java/org/tron/common/overlay/server/PeerServer.java +++ b/src/main/java/org/tron/common/overlay/server/PeerServer.java @@ -1,20 +1,3 @@ -/* - * Copyright (c) [2016] [ ] - * This file is part of the ethereumJ library. - * - * The ethereumJ library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The ethereumJ library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the ethereumJ library. If not, see . - */ package org.tron.common.overlay.server; import io.netty.bootstrap.ServerBootstrap; @@ -39,12 +22,8 @@ public class PeerServer { private ApplicationContext ctx; - public TronChannelInitializer tronChannelInitializer; - private boolean listening; - private EventLoopGroup bossGroup; - private EventLoopGroup workerGroup; private ChannelFuture channelFuture; @Autowired @@ -54,9 +33,9 @@ public PeerServer(final Args args, final ApplicationContext ctx) { public void start(int port) { - bossGroup = new NioEventLoopGroup(1); - workerGroup = new NioEventLoopGroup(args.getTcpNettyWorkThreadNum()); - tronChannelInitializer = ctx.getBean(TronChannelInitializer.class, ""); + EventLoopGroup bossGroup = new NioEventLoopGroup(1); + EventLoopGroup workerGroup = new NioEventLoopGroup(args.getTcpNettyWorkThreadNum()); + TronChannelInitializer tronChannelInitializer = ctx.getBean(TronChannelInitializer.class, ""); try { ServerBootstrap b = new ServerBootstrap(); diff --git a/src/main/java/org/tron/common/overlay/server/SyncPool.java b/src/main/java/org/tron/common/overlay/server/SyncPool.java index e2a9daec2fb..f444f0862e8 100644 --- a/src/main/java/org/tron/common/overlay/server/SyncPool.java +++ b/src/main/java/org/tron/common/overlay/server/SyncPool.java @@ -161,7 +161,7 @@ synchronized void logActivePeers() { } } - public synchronized List getActivePeers() { + public List getActivePeers() { List peers = Lists.newArrayList(); activePeers.forEach(peer -> { if (!peer.isDisconnect()) { @@ -199,10 +199,7 @@ public synchronized void onDisconnect(Channel peer) { } public boolean isCanConnect() { - if (passivePeersCount.get() >= maxActiveNodes * (1 - activeFactor)) { - return false; - } - return true; + return passivePeersCount.get() < maxActiveNodes * (1 - activeFactor); } public void close() { @@ -224,7 +221,7 @@ public AtomicInteger getActivePeersCount() { class NodeSelector implements Predicate { - Set nodesInUse; + private Set nodesInUse; public NodeSelector(Set nodesInUse) { this.nodesInUse = nodesInUse; diff --git a/src/main/java/org/tron/common/overlay/server/TronChannelInitializer.java b/src/main/java/org/tron/common/overlay/server/TronChannelInitializer.java index de6bedbff14..bc6ad417d37 100644 --- a/src/main/java/org/tron/common/overlay/server/TronChannelInitializer.java +++ b/src/main/java/org/tron/common/overlay/server/TronChannelInitializer.java @@ -42,7 +42,7 @@ public class TronChannelInitializer extends ChannelInitializer private ApplicationContext ctx; @Autowired - ChannelManager channelManager; + private ChannelManager channelManager; private String remoteId; @@ -77,10 +77,6 @@ public void initChannel(NioSocketChannel ch) throws Exception { } } - private boolean isInbound() { - return remoteId == null || remoteId.isEmpty(); - } - public void setPeerDiscoveryMode(boolean peerDiscoveryMode) { this.peerDiscoveryMode = peerDiscoveryMode; } diff --git a/src/main/java/org/tron/common/overlay/server/WireTrafficStats.java b/src/main/java/org/tron/common/overlay/server/WireTrafficStats.java index 88d8e5f79d1..75e7cb3fc19 100644 --- a/src/main/java/org/tron/common/overlay/server/WireTrafficStats.java +++ b/src/main/java/org/tron/common/overlay/server/WireTrafficStats.java @@ -58,26 +58,26 @@ public void close() { @ChannelHandler.Sharable static class TrafficStatHandler extends ChannelDuplexHandler { - private long outSizeTot; - private long inSizeTot; +// private long outSizeTot; +// private long inSizeTot; private AtomicLong outSize = new AtomicLong(); private AtomicLong inSize = new AtomicLong(); private AtomicLong outPackets = new AtomicLong(); private AtomicLong inPackets = new AtomicLong(); - private long lastTime = System.currentTimeMillis(); +// private long lastTime = System.currentTimeMillis(); public String stats() { - long out = outSize.getAndSet(0); - long outPac = outPackets.getAndSet(0); - long in = inSize.getAndSet(0); - long inPac = inPackets.getAndSet(0); - outSizeTot += out; - inSizeTot += in; - long curTime = System.currentTimeMillis(); - long d = (curTime - lastTime); - long outSpeed = out * 1000 / d; - long inSpeed = in * 1000 / d; - lastTime = curTime; +// long out = outSize.getAndSet(0); +// long outPac = outPackets.getAndSet(0); +// long in = inSize.getAndSet(0); +// long inPac = inPackets.getAndSet(0); +// outSizeTot += out; +// inSizeTot += in; +// long curTime = System.currentTimeMillis(); +// long d = (curTime - lastTime); +// long outSpeed = out * 1000 / d; +// long inSpeed = in * 1000 / d; +// lastTime = curTime; return ""; } diff --git a/src/main/java/org/tron/common/runtime/Runtime.java b/src/main/java/org/tron/common/runtime/Runtime.java index 56eeed1e3a6..d565d6f98d0 100644 --- a/src/main/java/org/tron/common/runtime/Runtime.java +++ b/src/main/java/org/tron/common/runtime/Runtime.java @@ -10,8 +10,6 @@ public interface Runtime { - boolean isCallConstant() throws ContractValidateException; - void execute() throws ContractValidateException, ContractExeException, VMIllegalException; void go(); diff --git a/src/main/java/org/tron/common/runtime/RuntimeImpl.java b/src/main/java/org/tron/common/runtime/RuntimeImpl.java index 7c01825c223..757e7238559 100644 --- a/src/main/java/org/tron/common/runtime/RuntimeImpl.java +++ b/src/main/java/org/tron/common/runtime/RuntimeImpl.java @@ -33,6 +33,7 @@ import org.tron.common.runtime.vm.program.Program; import org.tron.common.runtime.vm.program.Program.JVMStackOverFlowException; import org.tron.common.runtime.vm.program.Program.OutOfTimeException; +import org.tron.common.runtime.vm.program.Program.TransferException; import org.tron.common.runtime.vm.program.ProgramPrecompile; import org.tron.common.runtime.vm.program.ProgramResult; import org.tron.common.runtime.vm.program.invoke.ProgramInvoke; @@ -59,7 +60,6 @@ import org.tron.protos.Protocol; import org.tron.protos.Protocol.Block; import org.tron.protos.Protocol.SmartContract; -import org.tron.protos.Protocol.SmartContract.ABI; import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.Transaction.Contract.ContractType; import org.tron.protos.Protocol.Transaction.Result.contractResult; @@ -89,7 +89,10 @@ public class RuntimeImpl implements Runtime { //tx trace private TransactionTrace trace; - private boolean isStaticCall; + + @Getter + @Setter + private boolean isStaticCall = false; @Setter private boolean enableEventLinstener; @@ -312,6 +315,9 @@ public long getTotalEnergyLimitWithFixRatio(AccountCapsule creator, AccountCapsu public long getTotalEnergyLimit(AccountCapsule creator, AccountCapsule caller, TriggerSmartContract contract, long feeLimit, long callValue) throws ContractValidateException { + if (Objects.isNull(creator) && VMConfig.allowTvmConstantinople()) { + return getAccountEnergyLimitWithFixRatio(caller, feeLimit, callValue); + } // according to version if (VMConfig.getEnergyLimitHardFork()) { return getTotalEnergyLimitWithFixRatio(creator, caller, contract, feeLimit, callValue); @@ -445,7 +451,6 @@ private void create() this.blockCap); byte[] txId = new TransactionCapsule(trx).getTransactionId().getBytes(); this.program.setRootTransactionId(txId); - this.program.setRootCallConstant(isCallConstant()); if (enableEventLinstener && (EventPluginLoader.getInstance().isContractEventTriggerEnable() || EventPluginLoader.getInstance().isContractLogTriggerEnable()) @@ -465,8 +470,9 @@ && isCheckTransaction()) { deposit.createContract(contractAddress, new ContractCapsule(newSmartContract)); byte[] code = newSmartContract.getBytecode().toByteArray(); - deposit.saveCode(contractAddress, ProgramPrecompile.getCode(code)); - + if (!VMConfig.allowTvmConstantinople()) { + deposit.saveCode(contractAddress, ProgramPrecompile.getCode(code)); + } // transfer from callerAddress to contractAddress according to callValue if (callValue > 0) { transfer(this.deposit, callerAddress, contractAddress, callValue); @@ -540,14 +546,14 @@ private void call() } AccountCapsule caller = this.deposit.getAccount(callerAddress); long energyLimit; - if (isCallConstant(contractAddress)) { - isStaticCall = true; + if (isStaticCall) { energyLimit = Constant.ENERGY_LIMIT_IN_CONSTANT_TX; } else { AccountCapsule creator = this.deposit .getAccount(deployedContract.getInstance().getOriginAddress().toByteArray()); energyLimit = getTotalEnergyLimit(creator, caller, contract, feeLimit, callValue); } + long maxCpuTimeOfOneTx = deposit.getDbManager().getDynamicPropertiesStore() .getMaxCpuTimeOfOneTx() * Constant.ONE_THOUSAND; long thisTxCPULimitInUs = @@ -567,7 +573,6 @@ private void call() this.blockCap); byte[] txId = new TransactionCapsule(trx).getTransactionId().getBytes(); this.program.setRootTransactionId(txId); - this.program.setRootCallConstant(isCallConstant()); if (enableEventLinstener && (EventPluginLoader.getInstance().isContractEventTriggerEnable() @@ -611,7 +616,7 @@ public void go() { vm.play(program); result = program.getResult(); - if (isCallConstant()) { + if (isStaticCall) { long callValue = TransactionCapsule.getCallValue(trx.getRawData().getContract(0)); long callTokenValue = TransactionCapsule .getCallTokenValue(trx.getRawData().getContract(0)); @@ -634,6 +639,9 @@ public void go() { } } else { result.spendEnergy(saveCodeEnergy); + if (VMConfig.allowTvmConstantinople()) { + deposit.saveCode(program.getContractAddress().getNoLeadZeroesData(), code); + } } } @@ -644,7 +652,9 @@ public void go() { result.rejectInternalTransactions(); if (result.getException() != null) { - program.spendAllEnergy(); + if (!(result.getException() instanceof TransferException)) { + program.spendAllEnergy(); + } runtimeError = result.getException().getMessage(); throw result.getException(); } else { @@ -677,10 +687,10 @@ public void go() { result.rejectInternalTransactions(); runtimeError = result.getException().getMessage(); logger.info("timeout: {}", result.getException().getMessage()); - } catch (ContractValidateException e) { - logger.info("when check constant, {}", e.getMessage()); } catch (Throwable e) { - program.spendAllEnergy(); + if (!(e instanceof TransferException)) { + program.spendAllEnergy(); + } result = program.getResult(); result.rejectInternalTransactions(); if (Objects.isNull(result.getException())) { @@ -704,40 +714,6 @@ private static long getEnergyFee(long callerEnergyUsage, long callerEnergyFrozen .divide(BigInteger.valueOf(callerEnergyTotal)).longValueExact(); } - public boolean isCallConstant() throws ContractValidateException { - - TriggerSmartContract triggerContractFromTransaction = ContractCapsule - .getTriggerContractFromTransaction(trx); - if (TrxType.TRX_CONTRACT_CALL_TYPE == trxType) { - - ContractCapsule contract = deposit - .getContract(triggerContractFromTransaction.getContractAddress().toByteArray()); - if (contract == null) { - logger.info("contract: {} is not in contract store", Wallet - .encode58Check(triggerContractFromTransaction.getContractAddress().toByteArray())); - throw new ContractValidateException("contract: " + Wallet - .encode58Check(triggerContractFromTransaction.getContractAddress().toByteArray()) - + " is not in contract store"); - } - ABI abi = contract.getInstance().getAbi(); - if (Wallet.isConstant(abi, triggerContractFromTransaction)) { - return true; - } - } - return false; - } - - private boolean isCallConstant(byte[] address) throws ContractValidateException { - - if (TrxType.TRX_CONTRACT_CALL_TYPE == trxType) { - ABI abi = deposit.getContract(address).getInstance().getAbi(); - if (Wallet.isConstant(abi, ContractCapsule.getTriggerContractFromTransaction(trx))) { - return true; - } - } - return false; - } - public void finalization() { if (StringUtils.isEmpty(runtimeError)) { for (DataWord contract : result.getDeleteAccounts()) { diff --git a/src/main/java/org/tron/common/runtime/config/VMConfig.java b/src/main/java/org/tron/common/runtime/config/VMConfig.java index 18a99ebf41f..6dd500d310c 100644 --- a/src/main/java/org/tron/common/runtime/config/VMConfig.java +++ b/src/main/java/org/tron/common/runtime/config/VMConfig.java @@ -17,13 +17,10 @@ */ package org.tron.common.runtime.config; -import lombok.Getter; import lombok.Setter; import org.tron.common.utils.ForkController; import org.tron.core.config.Parameter.ForkBlockVersionConsts; -import org.tron.core.config.Parameter.ForkBlockVersionEnum; import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; /** * For developer only @@ -48,6 +45,9 @@ public class VMConfig { @Setter private static boolean ALLOW_TVM_TRANSFER_TRC10 = false; + @Setter + private static boolean ALLOW_TVM_CONSTANTINOPLE = false; + @Setter private static boolean ALLOW_MULTI_SIGN = false; @@ -84,6 +84,10 @@ public static void initAllowTvmTransferTrc10(long allow) { ALLOW_TVM_TRANSFER_TRC10 = allow == 1; } + public static void initAllowTvmConstantinople(long allow) { + ALLOW_TVM_CONSTANTINOPLE = allow == 1; + } + public static boolean getEnergyLimitHardFork() { return ENERGY_LIMIT_HARD_FORK; } @@ -92,6 +96,10 @@ public static boolean allowTvmTransferTrc10() { return ALLOW_TVM_TRANSFER_TRC10; } + public static boolean allowTvmConstantinople() { + return ALLOW_TVM_CONSTANTINOPLE; + } + public static boolean allowMultiSign() { return ALLOW_MULTI_SIGN; } diff --git a/src/main/java/org/tron/common/runtime/vm/DataWord.java b/src/main/java/org/tron/common/runtime/vm/DataWord.java index 009edbd424c..63c43e2bea7 100644 --- a/src/main/java/org/tron/common/runtime/vm/DataWord.java +++ b/src/main/java/org/tron/common/runtime/vm/DataWord.java @@ -17,6 +17,8 @@ */ package org.tron.common.runtime.vm; +import static org.tron.common.utils.ByteUtil.numberOfLeadingZeros; + import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; import org.spongycastle.util.Arrays; @@ -25,13 +27,12 @@ import org.tron.common.utils.FastByteComparisons; import org.tron.core.db.ByteArrayWrapper; -import java.io.UnsupportedEncodingException; import java.math.BigInteger; import java.nio.ByteBuffer; /** - * DataWord is the 32-byte array representation of a 256-bit number Calculations can be done on this - * word with other DataWords + * DataWord is the 32-byte array representation of a 256-bit number + * Calculations can be done on this word with other DataWords * * @author Roman Mandeleil * @since 01.06.2014 @@ -39,13 +40,19 @@ public class DataWord implements Comparable { /* Maximum value of the DataWord */ - public static final int DATAWORD_UNIT_SIZE = 32; + public static final int WORD_SIZE = 32; + public static final int MAX_POW = 256; public static final BigInteger _2_256 = BigInteger.valueOf(2).pow(256); public static final BigInteger MAX_VALUE = _2_256.subtract(BigInteger.ONE); - public static final DataWord ZERO = new DataWord( - new byte[32]); // don't push it in to the stack - public static final DataWord ZERO_EMPTY_ARRAY = new DataWord( - new byte[0]); // don't push it in to the stack + // TODO not safe + public static final DataWord ZERO = new DataWord(new byte[32]); // don't push it in to the stack + + public static DataWord ONE() { + return DataWord.of((byte)1); + } + public static DataWord ZERO() { + return new DataWord(new byte[32]); + } private byte[] data = new byte[32]; @@ -61,30 +68,37 @@ public DataWord(long num) { } private DataWord(ByteBuffer buffer) { - final ByteBuffer targetByteBuffer = ByteBuffer.allocate(32); + final ByteBuffer targetByteBuffer = ByteBuffer.allocate(WORD_SIZE); final byte[] array = buffer.array(); - System.arraycopy(array, 0, targetByteBuffer.array(), 32 - array.length, array.length); + System.arraycopy(array, 0, targetByteBuffer.array(), WORD_SIZE - array.length, array.length); this.data = targetByteBuffer.array(); } + public static DataWord of(byte num) { + byte[] bb = new byte[WORD_SIZE]; + bb[31] = num; + return new DataWord(bb); + + } + @JsonCreator public DataWord(String data) { this(Hex.decode(data)); } - public DataWord(ByteArrayWrapper wrappedData) { + public DataWord(ByteArrayWrapper wrappedData){ this(wrappedData.getData()); } public DataWord(byte[] data) { if (data == null) { this.data = ByteUtil.EMPTY_BYTE_ARRAY; - } else if (data.length == 32) { + } else if (data.length == WORD_SIZE) { this.data = data; - } else if (data.length <= 32) { - System.arraycopy(data, 0, this.data, 32 - data.length, data.length); + } else if (data.length < WORD_SIZE) { + System.arraycopy(data, 0, this.data, WORD_SIZE - data.length, data.length); } else { - throw new RuntimeException("Data word can't exceed 32 bytes: " + data); + throw new RuntimeException("Data word can't exceed 32 bytes: " + ByteUtil.toHexString(data)); } } @@ -93,13 +107,14 @@ public byte[] getData() { } /** - * be careful, this one will not throw Exception when data.length > DATAWORD_UNIT_SIZE + * be careful, this one will not throw Exception when data.length > WORD_SIZE + * @return */ public byte[] getClonedData() { byte[] ret = ByteUtil.EMPTY_BYTE_ARRAY; - if (data != null) { - ret = new byte[DATAWORD_UNIT_SIZE]; - int dataSize = Math.min(data.length, DATAWORD_UNIT_SIZE); + if (data != null){ + ret = new byte[WORD_SIZE]; + int dataSize = Math.min(data.length, WORD_SIZE); System.arraycopy(data, 0, ret, 0, dataSize); } return ret; @@ -118,8 +133,9 @@ public BigInteger value() { } /** - * Converts this DataWord to an int, checking for lost information. If this DataWord is out of the - * possible range for an int result then an ArithmeticException is thrown. + * Converts this DataWord to an int, checking for lost information. + * If this DataWord is out of the possible range for an int result + * then an ArithmeticException is thrown. * * @return this DataWord converted to an int. * @throws ArithmeticException - if this will not fit in an int. @@ -135,20 +151,20 @@ public int intValue() { } /** - * In case of int overflow returns Integer.MAX_VALUE otherwise works as #intValue() + * In case of int overflow returns Integer.MAX_VALUE + * otherwise works as #intValue() */ public int intValueSafe() { int bytesOccupied = bytesOccupied(); int intValue = intValue(); - if (bytesOccupied > 4 || intValue < 0) { - return Integer.MAX_VALUE; - } + if (bytesOccupied > 4 || intValue < 0) return Integer.MAX_VALUE; return intValue; } /** - * Converts this DataWord to a long, checking for lost information. If this DataWord is out of the - * possible range for a long result then an ArithmeticException is thrown. + * Converts this DataWord to a long, checking for lost information. + * If this DataWord is out of the possible range for a long result + * then an ArithmeticException is thrown. * * @return this DataWord converted to a long. * @throws ArithmeticException - if this will not fit in a long. @@ -164,14 +180,13 @@ public long longValue() { } /** - * In case of long overflow returns Long.MAX_VALUE otherwise works as #longValue() + * In case of long overflow returns Long.MAX_VALUE + * otherwise works as #longValue() */ public long longValueSafe() { int bytesOccupied = bytesOccupied(); long longValue = longValue(); - if (bytesOccupied > 8 || longValue < 0) { - return Long.MAX_VALUE; - } + if (bytesOccupied > 8 || longValue < 0) return Long.MAX_VALUE; return longValue; } @@ -179,11 +194,11 @@ public BigInteger sValue() { return new BigInteger(data); } - public static String bigIntValue(byte[] data) { + public static String bigIntValue(byte[] data) { return new BigInteger(data).toString(); } - public String bigIntValue() { + public String bigIntValue() { return new BigInteger(data).toString(); } @@ -198,9 +213,7 @@ public static boolean isZero(byte[] data) { public boolean isZero() { for (byte tmp : data) { - if (tmp != 0) { - return false; - } + if (tmp != 0) return false; } return true; } @@ -238,21 +251,10 @@ public DataWord xor(DataWord w2) { } public void negate() { + if (this.isZero()) return; - if (this.isZero()) { - return; - } - - for (int i = 0; i < this.data.length; ++i) { - this.data[i] = (byte) ~this.data[i]; - } - - for (int i = this.data.length - 1; i >= 0; --i) { - this.data[i] = (byte) (1 + this.data[i] & 0xFF); - if (this.data[i] != 0) { - break; - } - } + bnot(); + add(DataWord.ONE()); } public void bnot() { @@ -340,7 +342,7 @@ public void mod(DataWord word) { public void sMod(DataWord word) { if (word.isZero()) { - this.and(ZERO); + this.and(ZERO()); return; } @@ -380,13 +382,10 @@ public String toString() { public String toPrefixString() { byte[] pref = getNoLeadZeroesData(); - if (pref.length == 0) { - return ""; - } + if (pref.length == 0) return ""; - if (pref.length < 7) { + if (pref.length < 7) return Hex.toHexString(pref); - } return Hex.toHexString(pref).substring(0, 6); } @@ -407,14 +406,11 @@ public DataWord clone() { } + @Override public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; DataWord dataWord = (DataWord) o; @@ -429,9 +425,7 @@ public int hashCode() { @Override public int compareTo(DataWord o) { - if (o == null || o.getData() == null) { - return -1; - } + if (o == null || o.getData() == null) return -1; int result = FastByteComparisons.compareTo( data, 0, data.length, o.getData(), 0, o.getData().length); @@ -440,9 +434,8 @@ public int compareTo(DataWord o) { } public void signExtend(byte k) { - if (0 > k || k > 31) { + if (0 > k || k > 31) throw new IndexOutOfBoundsException(); - } byte mask = this.sValue().testBit((k * 8) + 7) ? (byte) 0xff : 0; for (int i = 31; i > k; i--) { this.data[31 - i] = mask; @@ -451,9 +444,7 @@ public void signExtend(byte k) { public int bytesOccupied() { int firstNonZero = ByteUtil.firstNonZeroByte(data); - if (firstNonZero == -1) { - return 0; - } + if (firstNonZero == -1) return 0; return 31 - firstNonZero + 1; } @@ -461,11 +452,63 @@ public boolean isHex(String hex) { return Hex.toHexString(data).equals(hex); } - public String asString() { + public String asString(){ return new String(getNoLeadZeroesData()); } public String toHexString() { return Hex.toHexString(data); } + + /** + * Shift left, both this and input arg are treated as unsigned + * @param arg + * @return this << arg + */ + public DataWord shiftLeft(DataWord arg) { + if (arg.value().compareTo(BigInteger.valueOf(MAX_POW)) >= 0) { + return DataWord.ZERO(); + } + + BigInteger result = value().shiftLeft(arg.intValueSafe()); + return new DataWord(ByteUtil.copyToArray(result.and(MAX_VALUE))); + } + + /** + * Shift right, both this and input arg are treated as unsigned + * @param arg + * @return this >> arg + */ + public DataWord shiftRight(DataWord arg) { + if (arg.value().compareTo(BigInteger.valueOf(MAX_POW)) >= 0) { + return DataWord.ZERO(); + } + + BigInteger result = value().shiftRight(arg.intValueSafe()); + return new DataWord(ByteUtil.copyToArray(result.and(MAX_VALUE))); + } + + /** + * Shift right, this is signed, while input arg is treated as unsigned + * @param arg + * @return this >> arg + */ + public DataWord shiftRightSigned(DataWord arg) { + if (arg.value().compareTo(BigInteger.valueOf(MAX_POW)) >= 0) { + if (this.isNegative()) { + DataWord result = ONE(); + result.negate(); + return result; + } else { + return ZERO(); + } + } + + BigInteger result = sValue().shiftRight(arg.intValueSafe()); + return new DataWord(ByteUtil.copyToArray(result.and(MAX_VALUE))); + } + + public static long sizeInWords(long bytesSize) { + return bytesSize == 0 ? 0 : (bytesSize - 1) / WORD_SIZE + 1; + } } diff --git a/src/main/java/org/tron/common/runtime/vm/EnergyCost.java b/src/main/java/org/tron/common/runtime/vm/EnergyCost.java index 3a7396c00d3..22cf4164bfe 100644 --- a/src/main/java/org/tron/common/runtime/vm/EnergyCost.java +++ b/src/main/java/org/tron/common/runtime/vm/EnergyCost.java @@ -61,6 +61,7 @@ public class EnergyCost { private final int EC_RECOVER = 3000; private final int EXT_CODE_SIZE = 20; private final int EXT_CODE_COPY = 20; + private final int EXT_CODE_HASH = 400; private final int NEW_ACCT_SUICIDE = 0; public int getSTEP() { @@ -271,6 +272,10 @@ public int getEXT_CODE_COPY() { return EXT_CODE_COPY; } + public int getEXT_CODE_HASH() { + return EXT_CODE_HASH; + } + private static EnergyCost instance = null; public static EnergyCost getInstance() { diff --git a/src/main/java/org/tron/common/runtime/vm/LogInfoTriggerParser.java b/src/main/java/org/tron/common/runtime/vm/LogInfoTriggerParser.java index 06adcb19c32..3a8448d5f16 100644 --- a/src/main/java/org/tron/common/runtime/vm/LogInfoTriggerParser.java +++ b/src/main/java/org/tron/common/runtime/vm/LogInfoTriggerParser.java @@ -7,13 +7,12 @@ import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.spongycastle.util.encoders.Hex; -import org.tron.common.crypto.Hash; -import org.tron.common.logsfilter.trigger.ContractLogTrigger; import org.tron.common.logsfilter.trigger.ContractTrigger; import org.tron.common.runtime.utils.MUtil; import org.tron.common.storage.Deposit; import org.tron.core.Wallet; import org.tron.core.capsule.ContractCapsule; +import org.tron.core.services.http.JsonFormat; import org.tron.protos.Protocol.SmartContract.ABI; public class LogInfoTriggerParser { @@ -42,8 +41,8 @@ public List parseLogInfos(List logInfos, Deposit depos return list; } - Map fullMap = new HashMap<>(); Map signMap = new HashMap<>(); + Map abiMap = new HashMap<>(); for (LogInfo logInfo : logInfos) { @@ -56,6 +55,7 @@ public List parseLogInfos(List logInfos, Deposit depos ContractCapsule contract = deposit.getContract(contractAddress); if (contract == null) { signMap.put(strContractAddr, originAddress); // mark as found. + abiMap.put(strContractAddr, ""); continue; } ABI abi = contract.getInstance().getAbi(); @@ -63,50 +63,21 @@ public List parseLogInfos(List logInfos, Deposit depos MUtil.convertToTronAddress(contract.getInstance().getOriginAddress().toByteArray())); signMap.put(strContractAddr, creatorAddr); // mark as found. - // calculate the sha3 of the event signature first. if (abi != null && abi.getEntrysCount() > 0) { - for (ABI.Entry entry : abi.getEntrysList()) { - if (entry.getType() != ABI.Entry.EntryType.Event || entry.getAnonymous()) { - continue; - } - String signature = getEntrySignature(entry); - String sha3 = Hex.toHexString(Hash.sha3(signature.getBytes())); - fullMap.put(strContractAddr + "_" + sha3, entry); - signMap.put(strContractAddr + "_" + sha3, signature); - } + abiMap.put(strContractAddr, JsonFormat.printToString(abi, false)); + } else { + abiMap.put(strContractAddr, ""); } } int index = 1; for (LogInfo logInfo : logInfos) { - byte[] contractAddress = MUtil.convertToTronAddress(logInfo.getAddress()); String strContractAddr = ArrayUtils.isEmpty(contractAddress) ? "" : Wallet.encode58Check(contractAddress); - List topics = logInfo.getTopics(); - ABI.Entry entry = null; - String signature = ""; - if (topics != null && topics.size() > 0 && !ArrayUtils.isEmpty(topics.get(0).getData()) - && fullMap.size() > 0) { - String firstTopic = topics.get(0).toString(); - entry = fullMap.get(strContractAddr + "_" + firstTopic); - signature = signMap.get(strContractAddr + "_" + firstTopic); - } - - boolean isEvent = (entry != null); - ContractTrigger event; - if (isEvent) { - event = new LogEventWrapper(); - ((LogEventWrapper) event).setTopicList(logInfo.getClonedTopics()); - ((LogEventWrapper) event).setData(logInfo.getClonedData()); - ((LogEventWrapper) event).setEventSignature(signature); - ((LogEventWrapper) event).setAbiEntry(entry); - } else { - event = new ContractLogTrigger(); - ((ContractLogTrigger) event).setTopicList(logInfo.getHexTopics()); - ((ContractLogTrigger) event).setData(logInfo.getHexData()); - } + String abiString = abiMap.get(strContractAddr); + ContractTrigger event = new ContractTrigger(); String creatorAddr = signMap.get(strContractAddr); event.setUniqueId(txId + "_" + index); event.setTransactionId(txId); @@ -116,10 +87,13 @@ public List parseLogInfos(List logInfos, Deposit depos event.setCreatorAddress(StringUtils.isEmpty(creatorAddr) ? "" : creatorAddr); event.setBlockNumber(blockNum); event.setTimeStamp(blockTimestamp); + event.setLogInfo(logInfo); + event.setAbiString(abiString); list.add(event); index++; } + return list; } diff --git a/src/main/java/org/tron/common/runtime/vm/OpCode.java b/src/main/java/org/tron/common/runtime/vm/OpCode.java index 234e23c916f..638ec970b80 100644 --- a/src/main/java/org/tron/common/runtime/vm/OpCode.java +++ b/src/main/java/org/tron/common/runtime/vm/OpCode.java @@ -127,6 +127,18 @@ public enum OpCode { * (0x1a) Retrieve single byte from word */ BYTE(0x1a, 2, 1, OpCode.Tier.VeryLowTier), + /** + * (0x1b) Shift left + */ + SHL(0x1b, 2, 1, OpCode.Tier.VeryLowTier), + /** + * (0x1c) Logical shift right + */ + SHR(0x1c, 2, 1, OpCode.Tier.VeryLowTier), + /** + * (0x1d) Arithmetic shift right + */ + SAR(0x1d, 2, 1, OpCode.Tier.VeryLowTier), /* Cryptographic Operations */ @@ -193,6 +205,10 @@ public enum OpCode { * (0x3c) Copy code running in current environment to memory with given offset */ EXTCODECOPY(0x3c, 4, 0, OpCode.Tier.ExtTier), + /** + * (0x3f) Returns the keccak256 hash of a contract’s code + */ + EXTCODEHASH(0x3f, 1, 1, OpCode.Tier.ExtTier), /* Block Information */ @@ -588,6 +604,11 @@ public enum OpCode { DELEGATECALL(0xf4, 6, 1, OpCode.Tier.SpecialTier, CallFlags.Call, CallFlags.Stateless, CallFlags.Delegate), + /** + * (0xf5) Skinny CREATE2, same as CREATE but with deterministic address + */ + CREATE2(0xf5, 4, 1, OpCode.Tier.SpecialTier), + /** * opcode that can be used to call another contract (or itself) while disallowing any * modifications to the state during the call (and its subcalls, if present). Any opcode that diff --git a/src/main/java/org/tron/common/runtime/vm/PrecompiledContracts.java b/src/main/java/org/tron/common/runtime/vm/PrecompiledContracts.java index 4c6974cd9ee..5c9840fe7e7 100644 --- a/src/main/java/org/tron/common/runtime/vm/PrecompiledContracts.java +++ b/src/main/java/org/tron/common/runtime/vm/PrecompiledContracts.java @@ -36,6 +36,8 @@ import java.util.List; import java.util.Objects; import java.util.Optional; +import lombok.Getter; +import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.tuple.Pair; import org.spongycastle.util.encoders.Hex; @@ -259,17 +261,9 @@ public ProgramResult getResult() { return result; } - public boolean isRootCallConstant() { - return isRootCallConstant; - } - - public void setRootCallConstant(boolean rootCallConstant) { - isRootCallConstant = rootCallConstant; - } - - private boolean isRootCallConstant; - - + @Setter + @Getter + private boolean isStaticCall; } public static class Identity extends PrecompiledContract { @@ -710,10 +704,10 @@ public long getEnergyForData(byte[] data) { @Override public Pair execute(byte[] data) { - if (isRootCallConstant()) { + if (isStaticCall()) { return Pair.of(true, new DataWord(0).getData()); } - if (data == null || data.length != 2 * DataWord.DATAWORD_UNIT_SIZE) { + if (data == null || data.length != 2 * DataWord.WORD_SIZE) { return Pair.of(false, new DataWord(0).getData()); } @@ -907,7 +901,7 @@ public long getEnergyForData(byte[] data) { @Override public Pair execute(byte[] data) { - if (isRootCallConstant()) { + if (isStaticCall()) { return Pair.of(true, new DataWord(0).getData()); } @@ -973,11 +967,11 @@ public long getEnergyForData(byte[] data) { @Override public Pair execute(byte[] data) { - if (isRootCallConstant()) { + if (isStaticCall()) { return Pair.of(true, new DataWord(0).getData()); } - if (data == null || data.length != 2 * DataWord.DATAWORD_UNIT_SIZE) { + if (data == null || data.length != 2 * DataWord.WORD_SIZE) { return Pair.of(false, new DataWord(0).getData()); } @@ -1049,11 +1043,11 @@ public long getEnergyForData(byte[] data) { @Override public Pair execute(byte[] data) { - if (isRootCallConstant()) { + if (isStaticCall()) { return Pair.of(true, new DataWord(0).getData()); } - if (data == null || data.length == 0 || (data.length % (2 * DataWord.DATAWORD_UNIT_SIZE) + if (data == null || data.length == 0 || (data.length % (2 * DataWord.WORD_SIZE) != 0)) { return Pair.of(false, new DataWord(0).getData()); } @@ -1134,11 +1128,11 @@ public long getEnergyForData(byte[] data) { @Override public Pair execute(byte[] data) { - if (isRootCallConstant()) { + if (isStaticCall()) { return Pair.of(true, new DataWord(0).getData()); } - if (data == null || data.length != DataWord.DATAWORD_UNIT_SIZE) { + if (data == null || data.length != DataWord.WORD_SIZE) { return Pair.of(false, new DataWord(0).getData()); } Contract.ProposalDeleteContract.Builder builder = Contract.ProposalDeleteContract @@ -1204,7 +1198,7 @@ public long getEnergyForData(byte[] data) { @Override public Pair execute(byte[] data) { - if (data == null || data.length != DataWord.DATAWORD_UNIT_SIZE) { + if (data == null || data.length != DataWord.WORD_SIZE) { return Pair.of(false, new DataWord(0).getData()); } DataWord address = new DataWord(data); @@ -1261,11 +1255,11 @@ public long getEnergyForData(byte[] data) { @Override public Pair execute(byte[] data) { -// if (isRootCallConstant()){ +// if (isStaticCall()){ // return Pair.of(true, new DataWord(0).getData()); // } // -// if (data == null || (data.length <= DataWord.DATAWORD_UNIT_SIZE * 2 || data.length > DataWord.DATAWORD_UNIT_SIZE * 3)) { +// if (data == null || (data.length <= DataWord.WORD_SIZE * 2 || data.length > DataWord.WORD_SIZE * 3)) { // return Pair.of(false, new DataWord(0).getData()); // } // @@ -1332,7 +1326,7 @@ public long getEnergyForData(byte[] data) { @Override public Pair execute(byte[] data) { - if (data == null || data.length != DataWord.DATAWORD_UNIT_SIZE * 2) { + if (data == null || data.length != DataWord.WORD_SIZE * 2) { return Pair.of(false, new DataWord(0).getData()); } diff --git a/src/main/java/org/tron/common/runtime/vm/VM.java b/src/main/java/org/tron/common/runtime/vm/VM.java index 8edcfb57a42..085e322b1df 100644 --- a/src/main/java/org/tron/common/runtime/vm/VM.java +++ b/src/main/java/org/tron/common/runtime/vm/VM.java @@ -6,8 +6,13 @@ import static org.tron.common.runtime.vm.OpCode.CALLTOKEN; import static org.tron.common.runtime.vm.OpCode.CALLTOKENID; import static org.tron.common.runtime.vm.OpCode.CALLTOKENVALUE; +import static org.tron.common.runtime.vm.OpCode.CREATE2; +import static org.tron.common.runtime.vm.OpCode.EXTCODEHASH; import static org.tron.common.runtime.vm.OpCode.PUSH1; import static org.tron.common.runtime.vm.OpCode.REVERT; +import static org.tron.common.runtime.vm.OpCode.SAR; +import static org.tron.common.runtime.vm.OpCode.SHL; +import static org.tron.common.runtime.vm.OpCode.SHR; import static org.tron.common.runtime.vm.OpCode.TOKENBALANCE; import static org.tron.common.utils.ByteUtil.EMPTY_BYTE_ARRAY; @@ -22,13 +27,14 @@ import org.tron.common.runtime.vm.program.Program.JVMStackOverFlowException; import org.tron.common.runtime.vm.program.Program.OutOfEnergyException; import org.tron.common.runtime.vm.program.Program.OutOfTimeException; +import org.tron.common.runtime.vm.program.Program.TransferException; import org.tron.common.runtime.vm.program.Stack; @Slf4j(topic = "VM") public class VM { private static final BigInteger _32_ = BigInteger.valueOf(32); - private static final String ENERGY_LOG_FORMATE = "{} Op: [{}] Energy: [{}] Deep: [{}] Hint: [{}]"; + private static final String ENERGY_LOG_FORMATE = "{} Op:[{}] Energy:[{}] Deep:[{}] Hint:[{}]"; // 3MB private static final BigInteger MEM_LIMIT = BigInteger.valueOf(3L * 1024 * 1024); @@ -92,6 +98,11 @@ public void step(Program program) { } } + if (!VMConfig.allowTvmConstantinople()) { + if (op == SHL || op == SHR || op == SAR || op == CREATE2 || op == EXTCODEHASH) { + throw Program.Exception.invalidOpCode(program.getCurrentOp()); + } + } program.setLastOp(op.val()); program.verifyStackSize(op.require()); program.verifyStackOverflow(op.require(), op.ret()); //Check not exceeding stack limits @@ -112,8 +123,8 @@ public void step(Program program) { case SUICIDE: energyCost = energyCosts.getSUICIDE(); DataWord suicideAddressWord = stack.get(stack.size() - 1); - if (isDeadAccount(program, suicideAddressWord) && - !program.getBalance(program.getContractAddress()).isZero()) { + if (isDeadAccount(program, suicideAddressWord) + && !program.getBalance(program.getContractAddress()).isZero()) { energyCost += energyCosts.getNEW_ACCT_SUICIDE(); } break; @@ -190,6 +201,9 @@ public void step(Program program) { memNeeded(stack.get(stack.size() - 2), stack.get(stack.size() - 4)), stack.get(stack.size() - 4).longValueSafe(), op); break; + case EXTCODEHASH: + energyCost = energyCosts.getEXT_CODE_HASH(); + break; case CALL: case CALLCODE: case DELEGATECALL: @@ -240,6 +254,14 @@ public void step(Program program) { energyCost = energyCosts.getCREATE() + calcMemEnergy(energyCosts, oldMemSize, memNeeded(stack.get(stack.size() - 2), stack.get(stack.size() - 3)), 0, op); break; + case CREATE2: + DataWord codeSize = stack.get(stack.size() - 3); + energyCost = energyCosts.getCREATE(); + energyCost += calcMemEnergy(energyCosts, oldMemSize, + memNeeded(stack.get(stack.size() - 2), stack.get(stack.size() - 3)), 0, op); + energyCost += DataWord.sizeInWords(codeSize.intValueSafe()) * energyCosts.getSHA3_WORD(); + + break; case LOG0: case LOG1: case LOG2: @@ -593,6 +615,45 @@ public void step(Program program) { program.step(); } break; + case SHL: { + DataWord word1 = program.stackPop(); + DataWord word2 = program.stackPop(); + final DataWord result = word2.shiftLeft(word1); + + if (logger.isInfoEnabled()) { + hint = "" + result.value(); + } + + program.stackPush(result); + program.step(); + } + break; + case SHR: { + DataWord word1 = program.stackPop(); + DataWord word2 = program.stackPop(); + final DataWord result = word2.shiftRight(word1); + + if (logger.isInfoEnabled()) { + hint = "" + result.value(); + } + + program.stackPush(result); + program.step(); + } + break; + case SAR: { + DataWord word1 = program.stackPop(); + DataWord word2 = program.stackPop(); + final DataWord result = word2.shiftRightSigned(word1); + + if (logger.isInfoEnabled()) { + hint = "" + result.value(); + } + + program.stackPush(result); + program.step(); + } + break; case ADDMOD: { DataWord word1 = program.stackPop(); DataWord word2 = program.stackPop(); @@ -812,8 +873,8 @@ public void step(Program program) { program.stackPush(codeLength); program.step(); + break; } - break; case CODECOPY: case EXTCODECOPY: { @@ -848,6 +909,13 @@ public void step(Program program) { program.memorySave(memOffset, codeCopy); program.step(); + break; + } + case EXTCODEHASH: { + DataWord address = program.stackPop(); + byte[] codeHash = program.getCodeHashAt(address); + program.stackPush(codeHash); + program.step(); } break; case GASPRICE: { @@ -962,8 +1030,8 @@ public void step(Program program) { program.stackPush(word_1.clone()); program.step(); + break; } - break; case SWAP1: case SWAP2: case SWAP3: @@ -984,8 +1052,8 @@ public void step(Program program) { int n = op.val() - OpCode.SWAP1.val() + 2; stack.swap(stack.size() - 1, stack.size() - n); program.step(); + break; } - break; case LOG0: case LOG1: case LOG2: @@ -1019,8 +1087,8 @@ public void step(Program program) { program.getResult().addLogInfo(logInfo); program.step(); + break; } - break; case MLOAD: { DataWord addr = program.stackPop(); DataWord data = program.memoryLoad(addr); @@ -1194,8 +1262,8 @@ public void step(Program program) { } program.stackPush(data); + break; } - break; case JUMPDEST: { program.step(); } @@ -1212,6 +1280,18 @@ public void step(Program program) { program.step(); } break; + case CREATE2: { + if (program.isStaticCall()) { + throw new Program.StaticCallModificationException(); + } + DataWord value = program.stackPop(); + DataWord inOffset = program.stackPop(); + DataWord inSize = program.stackPop(); + DataWord salt = program.stackPop(); + program.createContract2(value, inOffset, inSize, salt); + program.step(); + } + break; case TOKENBALANCE: { DataWord tokenId = program.stackPop(); DataWord address = program.stackPop(); @@ -1290,8 +1370,8 @@ public void step(Program program) { } program.step(); + break; } - break; case RETURN: case REVERT: { DataWord offset = program.stackPop(); @@ -1312,8 +1392,8 @@ public void step(Program program) { if (op == REVERT) { program.getResult().setRevert(); } + break; } - break; case SUICIDE: { if (program.isStaticCall()) { throw new Program.StaticCallModificationException(); @@ -1337,7 +1417,9 @@ public void step(Program program) { program.setPreviouslyExecutedOp(op.val()); } catch (RuntimeException e) { logger.info("VM halted: [{}]", e.getMessage()); - program.spendAllEnergy(); + if (!(e instanceof TransferException)) { + program.spendAllEnergy(); + } program.resetFutureRefund(); program.stop(); throw e; diff --git a/src/main/java/org/tron/common/runtime/vm/program/ContractState.java b/src/main/java/org/tron/common/runtime/vm/program/ContractState.java index ef212dd4020..2fa3afbf600 100644 --- a/src/main/java/org/tron/common/runtime/vm/program/ContractState.java +++ b/src/main/java/org/tron/common/runtime/vm/program/ContractState.java @@ -111,13 +111,23 @@ public ContractCapsule getContract(byte[] codeHash) { } @Override - public void saveCode(byte[] addr, byte[] code) { - deposit.saveCode(addr, code); + public void updateContract(byte[] address, ContractCapsule contractCapsule) { + deposit.updateContract(address, contractCapsule); } @Override - public byte[] getCode(byte[] addr) { - return deposit.getCode(addr); + public void updateAccount(byte[] address, AccountCapsule accountCapsule) { + deposit.updateAccount(address, accountCapsule); + } + + @Override + public void saveCode(byte[] address, byte[] code) { + deposit.saveCode(address, code); + } + + @Override + public byte[] getCode(byte[] address) { + return deposit.getCode(address); } @Override diff --git a/src/main/java/org/tron/common/runtime/vm/program/Program.java b/src/main/java/org/tron/common/runtime/vm/program/Program.java index 24dc9eb5d0b..e075592fcc4 100644 --- a/src/main/java/org/tron/common/runtime/vm/program/Program.java +++ b/src/main/java/org/tron/common/runtime/vm/program/Program.java @@ -15,6 +15,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ + package org.tron.common.runtime.vm.program; import static java.lang.StrictMath.min; @@ -45,6 +46,7 @@ import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.tuple.Pair; import org.spongycastle.util.encoders.Hex; +import org.tron.common.crypto.Hash; import org.tron.common.runtime.config.VMConfig; import org.tron.common.runtime.vm.DataWord; import org.tron.common.runtime.vm.EnergyCost; @@ -75,7 +77,9 @@ import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.TronException; import org.tron.protos.Protocol; +import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.SmartContract; +import org.tron.protos.Protocol.SmartContract.Builder; /** * @author Roman Mandeleil @@ -88,13 +92,14 @@ public class Program { private static final int MAX_DEPTH = 64; //Max size for stack checks private static final int MAX_STACK_SIZE = 1024; - public static final String VALIDATE_FOR_SMART_CONTRACT_FAILURE = "validateForSmartContract failure"; + private static final String VALIDATE_FOR_SMART_CONTRACT_FAILURE = + "validateForSmartContract failure:%s"; + private static final String INVALID_TOKEN_ID_MSG = "not valid token id"; private BlockCapsule blockCap; private long nonce; private byte[] rootTransactionId; - private Boolean isRootCallConstant; private InternalTransaction internalTransaction; @@ -164,14 +169,6 @@ public void setNonce(long nonceValue) { nonce = nonceValue; } - public Boolean getRootCallConstant() { - return isRootCallConstant; - } - - public void setRootCallConstant(Boolean rootCallConstant) { - isRootCallConstant = rootCallConstant; - } - public ProgramPrecompile getProgramPrecompile() { if (programPrecompile == null) { programPrecompile = ProgramPrecompile.compile(ops); @@ -249,6 +246,11 @@ public void stackPush(byte[] data) { stackPush(new DataWord(data)); } + public void stackPush(DataWord stackWord) { + verifyStackOverflow(0, 1); //Sanity Check + stack.push(stackWord); + } + public void stackPushZero() { stackPush(new DataWord(0)); } @@ -258,11 +260,6 @@ public void stackPushOne() { stackPush(stackWord); } - public void stackPush(DataWord stackWord) { - verifyStackOverflow(0, 1); //Sanity Check - stack.push(stackWord); - } - public Stack getStack() { return this.stack; } @@ -319,7 +316,7 @@ public DataWord stackPop() { } /** - * Verifies that the stack is at least stackSize + * . Verifies that the stack is at least stackSize * * @param stackSize int * @throws StackTooSmallException If the stack is smaller than stackSize @@ -345,22 +342,12 @@ public void memorySave(DataWord addrB, DataWord value) { memory.write(addrB.intValue(), value.getData(), value.getData().length, false); } - public void memorySaveLimited(int addr, byte[] data, int dataSize) { - memory.write(addr, data, dataSize, true); - } - public void memorySave(int addr, byte[] value) { memory.write(addr, value, value.length, false); } - public void memoryExpand(DataWord outDataOffs, DataWord outDataSize) { - if (!outDataSize.isZero()) { - memory.extend(outDataOffs.intValue(), outDataSize.intValue()); - } - } - /** - * Allocates a piece of memory and stores value at given offset address + * . Allocates a piece of memory and stores value at given offset address * * @param addr is the offset address * @param allocSize size of memory needed to write @@ -370,6 +357,15 @@ public void memorySave(int addr, int allocSize, byte[] value) { memory.extendAndWrite(addr, allocSize, value); } + public void memorySaveLimited(int addr, byte[] data, int dataSize) { + memory.write(addr, data, dataSize, true); + } + + public void memoryExpand(DataWord outDataOffs, DataWord outDataSize) { + if (!outDataSize.isZero()) { + memory.extend(outDataOffs.intValue(), outDataSize.intValue()); + } + } public DataWord memoryLoad(DataWord addr) { return memory.readWord(addr.intValue()); @@ -384,7 +380,7 @@ public byte[] memoryChunk(int offset, int size) { } /** - * Allocates extra memory in the program for a specified size, calculated from a given offset + * . Allocates extra memory in the program for a specified size, calculated from a given offset * * @param offset the memory address offset * @param size the number of bytes to allocate @@ -426,6 +422,10 @@ public void suicide(DataWord obtainerAddress) { transferAllToken(getContractState(), owner, obtainer); } } catch (ContractValidateException e) { + if (VMConfig.allowTvmConstantinople()) { + throw new TransferException( + "transfer all token or transfer all trx failed in suicide: %s", e.getMessage()); + } throw new BytecodeExecutionException("transfer failure"); } } @@ -444,48 +444,78 @@ public void createContract(DataWord value, DataWord memStart, DataWord memSize) stackPushZero(); return; } + // [1] FETCH THE CODE FROM THE MEMORY + byte[] programCode = memoryChunk(memStart.intValue(), memSize.intValue()); - byte[] senderAddress = convertToTronAddress(this.getContractAddress().getLast20Bytes()); + byte[] newAddress = Wallet + .generateContractAddress(rootTransactionId, nonce); - long endowment = value.value().longValueExact(); - if (getContractState().getBalance(senderAddress) < endowment) { - stackPushZero(); - return; - } + createContractImpl(value, programCode, newAddress, false); + } - // [1] FETCH THE CODE FROM THE MEMORY - byte[] programCode = memoryChunk(memStart.intValue(), memSize.intValue()); + private void createContractImpl(DataWord value, byte[] programCode, byte[] newAddress, + boolean isCreate2) { + byte[] senderAddress = convertToTronAddress(this.getContractAddress().getLast20Bytes()); if (logger.isDebugEnabled()) { logger.debug("creating a new contract inside contract run: [{}]", Hex.toHexString(senderAddress)); } - byte[] newAddress = Wallet - .generateContractAddress(rootTransactionId, nonce); + long endowment = value.value().longValueExact(); + if (getContractState().getBalance(senderAddress) < endowment) { + stackPushZero(); + return; + } - AccountCapsule existingAddr = getContractState().getAccount(newAddress); - boolean contractAlreadyExists = existingAddr != null; + AccountCapsule existingAccount = getContractState().getAccount(newAddress); + boolean contractAlreadyExists = existingAccount != null; + if (VMConfig.allowTvmConstantinople()) { + contractAlreadyExists = + contractAlreadyExists && isContractExist(existingAccount, getContractState()); + } Deposit deposit = getContractState().newDepositChild(); + if (VMConfig.allowTvmConstantinople()) { + if (existingAccount == null) { + deposit.createAccount(newAddress, "CreatedByContract", + AccountType.Contract); + } else if (!contractAlreadyExists) { + existingAccount.updateAccountType(AccountType.Contract); + existingAccount.clearDelegatedResource(); + deposit.updateAccount(newAddress, existingAccount); + } - //In case of hashing collisions, check for any balance before createAccount() - long oldBalance = deposit.getBalance(newAddress); - - SmartContract newSmartContract = SmartContract.newBuilder() - .setContractAddress(ByteString.copyFrom(newAddress)).setConsumeUserResourcePercent(100) - .setOriginAddress(ByteString.copyFrom(senderAddress)).build(); - deposit.createContract(newAddress, new ContractCapsule(newSmartContract)); - deposit.createAccount(newAddress, "CreatedByContract", - Protocol.AccountType.Contract); + if (!contractAlreadyExists) { + Builder builder = SmartContract.newBuilder(); + builder.setContractAddress(ByteString.copyFrom(newAddress)) + .setConsumeUserResourcePercent(100) + .setOriginAddress(ByteString.copyFrom(senderAddress)); + if (isCreate2) { + builder.setTrxHash(ByteString.copyFrom(rootTransactionId)); + } + SmartContract newSmartContract = builder.build(); + deposit.createContract(newAddress, new ContractCapsule(newSmartContract)); + } + } else { + deposit.createAccount(newAddress, "CreatedByContract", + Protocol.AccountType.Contract); + SmartContract newSmartContract = SmartContract.newBuilder() + .setContractAddress(ByteString.copyFrom(newAddress)).setConsumeUserResourcePercent(100) + .setOriginAddress(ByteString.copyFrom(senderAddress)).build(); + deposit.createContract(newAddress, new ContractCapsule(newSmartContract)); + // In case of hashing collisions, check for any balance before createAccount() + long oldBalance = deposit.getBalance(newAddress); + deposit.addBalance(newAddress, oldBalance); + } - deposit.addBalance(newAddress, oldBalance); // [4] TRANSFER THE BALANCE long newBalance = 0L; if (!byTestingSuite() && endowment > 0) { try { TransferActuator.validateForSmartContract(deposit, senderAddress, newAddress, endowment); } catch (ContractValidateException e) { + // TODO: unreachable exception throw new BytecodeExecutionException(VALIDATE_FOR_SMART_CONTRACT_FAILURE); } deposit.addBalance(senderAddress, -endowment); @@ -517,7 +547,6 @@ this, new DataWord(newAddress), getContractAddress(), value, new DataWord(0), VM vm = new VM(config); Program program = new Program(programCode, programInvoke, internalTx, config, this.blockCap); program.setRootTransactionId(this.rootTransactionId); - program.setRootCallConstant(this.isRootCallConstant); vm.play(program); createResult = program.getResult(); getTrace().merge(program.getTrace()); @@ -536,7 +565,7 @@ this, new DataWord(newAddress), getContractAddress(), value, new DataWord(0), if (!createResult.isRevert()) { if (afterSpend < 0) { createResult.setException( - Program.Exception.notEnoughSpendEnergy("No energy to save just created contract code", + Exception.notEnoughSpendEnergy("No energy to save just created contract code", saveCodeEnergy, programInvoke.getEnergyLimit() - createResult.getEnergyUsed())); } else { createResult.spendEnergy(saveCodeEnergy); @@ -588,7 +617,7 @@ public void refundEnergyAfterVM(DataWord energyLimit, ProgramResult result) { } /** - * That method is for internal code invocations + * . That method is for internal code invocations *

* - Normal calls invoke a specified contract which updates itself - Stateless calls invoke code * from another contract, within the context of the caller @@ -621,7 +650,17 @@ public void callToAddress(MessageCall msg) { Deposit deposit = getContractState().newDepositChild(); // 2.1 PERFORM THE VALUE (endowment) PART - long endowment = msg.getEndowment().value().longValueExact(); + long endowment; + try { + endowment = msg.getEndowment().value().longValueExact(); + } catch (ArithmeticException e) { + if (VMConfig.allowTvmConstantinople()) { + refundEnergy(msg.getEnergy().longValue(), "endowment out of long range"); + throw new TransferException("endowment out of long range"); + } else { + throw e; + } + } // transfer trx validation byte[] tokenId = null; @@ -636,9 +675,8 @@ public void callToAddress(MessageCall msg) { refundEnergy(msg.getEnergy().longValue(), "refund energy from message call"); return; } - } - // transfer trc10 token validation - else { + } else { + // transfer trc10 token validation tokenId = String.valueOf(msg.getTokenId().longValue()).getBytes(); long senderBalance = deposit.getTokenBalance(senderAddress, tokenId); if (senderBalance < endowment) { @@ -668,6 +706,10 @@ public void callToAddress(MessageCall msg) { TransferActuator .validateForSmartContract(deposit, senderAddress, contextAddress, endowment); } catch (ContractValidateException e) { + if (VMConfig.allowTvmConstantinople()) { + refundEnergy(msg.getEnergy().longValue(), "refund energy from message call"); + throw new TransferException("transfer trx failed: %s", e.getMessage()); + } throw new BytecodeExecutionException(VALIDATE_FOR_SMART_CONTRACT_FAILURE); } deposit.addBalance(senderAddress, -endowment); @@ -677,6 +719,10 @@ public void callToAddress(MessageCall msg) { TransferAssetActuator.validateForSmartContract(deposit, senderAddress, contextAddress, tokenId, endowment); } catch (ContractValidateException e) { + if (VMConfig.allowTvmConstantinople()) { + refundEnergy(msg.getEnergy().longValue(), "refund energy from message call"); + throw new TransferException("transfer trc10 failed: %s", e.getMessage()); + } throw new BytecodeExecutionException(VALIDATE_FOR_SMART_CONTRACT_FAILURE); } deposit.addTokenBalance(senderAddress, tokenId, -endowment); @@ -709,7 +755,6 @@ this, new DataWord(contextAddress), Program program = new Program(programCode, programInvoke, internalTx, config, this.blockCap); program.setRootTransactionId(this.rootTransactionId); - program.setRootCallConstant(this.isRootCallConstant); vm.play(program); callResult = program.getResult(); @@ -784,7 +829,8 @@ public void resetNonce() { public void spendEnergy(long energyValue, String opName) { if (getEnergylimitLeftLong() < energyValue) { throw new OutOfEnergyException( - "Not enough energy for '%s' operation executing: curInvokeEnergyLimit[%d], curOpEnergy[%d], usedEnergy[%d]", + "Not enough energy for '%s' operation executing: curInvokeEnergyLimit[%d]," + + " curOpEnergy[%d], usedEnergy[%d]", opName, invoke.getEnergyLimit(), energyValue, getResult().getEnergyUsed()); } getResult().spendEnergy(energyValue); @@ -800,8 +846,8 @@ public void checkCPUTimeLimit(String opName) { long vmNowInUs = System.nanoTime() / 1000; if (vmNowInUs > getVmShouldEndInUs()) { logger.info( - "minTimeRatio: {}, maxTimeRatio: {}, vm should end time in us: {}, " + - "vm now time in us: {}, vm start time in us: {}", + "minTimeRatio: {}, maxTimeRatio: {}, vm should end time in us: {}, " + + "vm now time in us: {}, vm start time in us: {}", Args.getInstance().getMinTimeRatio(), Args.getInstance().getMaxTimeRatio(), getVmShouldEndInUs(), vmNowInUs, getVmStartInUs()); throw Exception.notEnoughTime(opName); @@ -845,6 +891,29 @@ public byte[] getCodeAt(DataWord address) { return nullToEmpty(code); } + public byte[] getCodeHashAt(DataWord address) { + byte[] tronAddr = convertToTronAddress(address.getLast20Bytes()); + AccountCapsule account = getContractState().getAccount(tronAddr); + if (account != null) { + ContractCapsule contract = getContractState().getContract(tronAddr); + byte[] codeHash; + if (contract != null) { + codeHash = contract.getCodeHash(); + if (ByteUtil.isNullOrZeroArray(codeHash)) { + byte[] code = getCodeAt(address); + codeHash = Hash.sha3(code); + contract.setCodeHash(codeHash); + getContractState().updateContract(tronAddr, contract); + } + } else { + codeHash = Hash.sha3(new byte[0]); + } + return codeHash; + } else { + return EMPTY_BYTE_ARRAY; + } + } + public DataWord getContractAddress() { return invoke.getContractAddress().clone(); } @@ -1169,6 +1238,15 @@ public static String stringifyMultiline(byte[] code) { return sb.toString(); } + public void createContract2(DataWord value, DataWord memStart, DataWord memSize, DataWord salt) { + byte[] senderAddress = convertToTronAddress(this.getCallerAddress().getLast20Bytes()); + byte[] programCode = memoryChunk(memStart.intValue(), memSize.intValue()); + + byte[] contractAddress = Wallet + .generateContractAddress2(senderAddress, salt.getData(), programCode); + createContractImpl(value, programCode, contractAddress, true); + } + static class ByteCodeIterator { private byte[] code; @@ -1235,8 +1313,8 @@ static BitSet buildReachableBytecodesMask(byte[] code) { gotos.add(jumpPC); } } - if (it.getCurOpcode() == OpCode.JUMP || it.getCurOpcode() == OpCode.RETURN || - it.getCurOpcode() == OpCode.STOP) { + if (it.getCurOpcode() == OpCode.JUMP || it.getCurOpcode() == OpCode.RETURN + || it.getCurOpcode() == OpCode.STOP) { if (gotos.isEmpty()) { break; } @@ -1318,9 +1396,8 @@ public void callToPrecompiledAddress(MessageCall msg, // transfer trx validation if (!isTokenTransfer) { senderBalance = deposit.getBalance(senderAddress); - } - // transfer trc10 token validation - else { + } else { + // transfer trc10 token validation tokenId = String.valueOf(msg.getTokenId().longValue()).getBytes(); senderBalance = deposit.getTokenBalance(senderAddress, tokenId); } @@ -1362,12 +1439,12 @@ public void callToPrecompiledAddress(MessageCall msg, this.stackPushZero(); } else { // Delegate or not. if is delegated, we will use msg sender, otherwise use contract address - contract.setCallerAddress(convertToTronAddress(msg.getType().callIsDelegate() ? - getCallerAddress().getLast20Bytes() : getContractAddress().getLast20Bytes())); + contract.setCallerAddress(convertToTronAddress(msg.getType().callIsDelegate() + ? getCallerAddress().getLast20Bytes() : getContractAddress().getLast20Bytes())); // this is the depositImpl, not contractState as above contract.setDeposit(deposit); contract.setResult(this.result); - contract.setRootCallConstant(getRootCallConstant().booleanValue()); + contract.setStaticCall(isStaticCall()); Pair out = contract.execute(data); if (out.getLeft()) { // success @@ -1398,16 +1475,14 @@ public interface ProgramOutListener { } /** - * check TokenId - * - * TokenId \ isTransferToken --------------------------------------------------------------------------------------------- - * false true --------------------------------------------------------------------------------------------- + * check TokenId TokenId \ isTransferToken ------------------------------------------------------------------- + * false true ----------------------------------------------- * (-∞,Long.Min) Not possible error: msg.getTokenId().value().longValueExact() * --------------------------------------------------------------------------------------------- * [Long.Min, 0) Not possible error * --------------------------------------------------------------------------------------------- 0 * allowed and only allowed error (guaranteed in CALLTOKEN) transfertoken id=0 - * should not transfer trx) --------------------------------------------------------------------------------------------- + * should not transfer trx) --------------------------------------------------------------------- * (0-100_0000] Not possible error * --------------------------------------------------------------------------------------------- * (100_0000, Long.Max] Not possible allowed @@ -1418,14 +1493,27 @@ public interface ProgramOutListener { public void checkTokenId(MessageCall msg) { if (VMConfig.allowMultiSign()) { //allowMultiSign proposal // tokenid should not get Long type overflow - long tokenId = msg.getTokenId().sValue().longValueExact(); + long tokenId; + try { + tokenId = msg.getTokenId().sValue().longValueExact(); + } catch (ArithmeticException e) { + if (VMConfig.allowTvmConstantinople()) { + refundEnergy(msg.getEnergy().longValue(), "refund energy from message call"); + throw new TransferException(VALIDATE_FOR_SMART_CONTRACT_FAILURE, INVALID_TOKEN_ID_MSG); + } + throw e; + } // tokenId can only be 0 when isTokenTransferMsg == false // or tokenId can be (MIN_TOKEN_ID, Long.Max] when isTokenTransferMsg == true - if ((tokenId <= VMConstant.MIN_TOKEN_ID && tokenId != 0) || - (tokenId == 0 && msg.isTokenTransferMsg())) { + if ((tokenId <= VMConstant.MIN_TOKEN_ID && tokenId != 0) + || (tokenId == 0 && msg.isTokenTransferMsg())) { // tokenId == 0 is a default value for token id DataWord. + if (VMConfig.allowTvmConstantinople()) { + refundEnergy(msg.getEnergy().longValue(), "refund energy from message call"); + throw new TransferException(VALIDATE_FOR_SMART_CONTRACT_FAILURE, INVALID_TOKEN_ID_MSG); + } throw new BytecodeExecutionException( - VALIDATE_FOR_SMART_CONTRACT_FAILURE + ", not valid token id"); + String.format(VALIDATE_FOR_SMART_CONTRACT_FAILURE, INVALID_TOKEN_ID_MSG)); } } } @@ -1441,11 +1529,20 @@ public boolean isTokenTransfer(MessageCall msg) { public void checkTokenIdInTokenBalance(DataWord tokenIdDataWord) { if (VMConfig.allowMultiSign()) { //allowMultiSigns proposal // tokenid should not get Long type overflow - long tokenId = tokenIdDataWord.sValue().longValueExact(); + long tokenId; + try { + tokenId = tokenIdDataWord.sValue().longValueExact(); + } catch (ArithmeticException e) { + if (VMConfig.allowTvmConstantinople()) { + throw new TransferException(VALIDATE_FOR_SMART_CONTRACT_FAILURE, INVALID_TOKEN_ID_MSG); + } + throw e; + } + // or tokenId can only be (MIN_TOKEN_ID, Long.Max] if (tokenId <= VMConstant.MIN_TOKEN_ID) { throw new BytecodeExecutionException( - VALIDATE_FOR_SMART_CONTRACT_FAILURE + ", not valid token id"); + String.format(VALIDATE_FOR_SMART_CONTRACT_FAILURE, INVALID_TOKEN_ID_MSG)); } } } @@ -1463,6 +1560,13 @@ public BytecodeExecutionException(String message) { } } + public static class TransferException extends BytecodeExecutionException { + + public TransferException(String message, Object... args) { + super(format(message, args)); + } + } + @SuppressWarnings("serial") public static class OutOfEnergyException extends BytecodeExecutionException { @@ -1568,6 +1672,11 @@ public static OutOfEnergyException notEnoughOpEnergy(OpCode op, long opEnergy, programEnergy); } + public static OutOfEnergyException notEnoughOpEnergy(OpCode op, DataWord opEnergy, + DataWord programEnergy) { + return notEnoughOpEnergy(op, opEnergy.longValue(), programEnergy.longValue()); + } + public static OutOfEnergyException notEnoughSpendEnergy(String hint, long needEnergy, long leftEnergy) { return new OutOfEnergyException( @@ -1575,12 +1684,6 @@ public static OutOfEnergyException notEnoughSpendEnergy(String hint, long needEn leftEnergy); } - public static OutOfEnergyException notEnoughOpEnergy(OpCode op, DataWord opEnergy, - DataWord programEnergy) { - return notEnoughOpEnergy(op, opEnergy.longValue(), programEnergy.longValue()); - } - - public static OutOfTimeException notEnoughTime(String op) { return new OutOfTimeException( "CPU timeout for '%s' operation executing", op); @@ -1645,14 +1748,14 @@ public DataWord getCreateEnergy(DataWord availableEnergy) { } /** - * used mostly for testing reasons + * . used mostly for testing reasons */ public byte[] getMemory() { return memory.read(0, memory.size()); } /** - * used mostly for testing reasons + * . used mostly for testing reasons */ public void initMem(byte[] data) { this.memory.write(0, data, data.length, false); @@ -1662,4 +1765,7 @@ public long getVmStartInUs() { return this.invoke.getVmStartInUs(); } + private boolean isContractExist(AccountCapsule existingAddr, Deposit deposit) { + return deposit.getContract(existingAddr.getAddress().toByteArray()) != null; + } } diff --git a/src/main/java/org/tron/common/runtime/vm/program/ProgramPrecompile.java b/src/main/java/org/tron/common/runtime/vm/program/ProgramPrecompile.java index 39e0f658692..df2a0237a89 100644 --- a/src/main/java/org/tron/common/runtime/vm/program/ProgramPrecompile.java +++ b/src/main/java/org/tron/common/runtime/vm/program/ProgramPrecompile.java @@ -20,6 +20,7 @@ import java.util.HashSet; import java.util.Set; import lombok.extern.slf4j.Slf4j; +import org.tron.common.runtime.config.VMConfig; import org.tron.common.runtime.vm.DataWord; import org.tron.common.runtime.vm.OpCode; @@ -79,7 +80,11 @@ public static byte[] getCode(byte[] ops) { i += op.asInt() - OpCode.PUSH1.asInt() + 1; } } - return new DataWord(0).getData(); + if (VMConfig.allowTvmConstantinople()) { + return new byte[0]; + } else { + return new DataWord(0).getData(); + } } public boolean hasJumpDest(int pc) { diff --git a/src/main/java/org/tron/common/runtime/vm/program/Storage.java b/src/main/java/org/tron/common/runtime/vm/program/Storage.java index 4196b377336..3a910d8779f 100644 --- a/src/main/java/org/tron/common/runtime/vm/program/Storage.java +++ b/src/main/java/org/tron/common/runtime/vm/program/Storage.java @@ -7,6 +7,7 @@ import lombok.Getter; import org.tron.common.crypto.Hash; import org.tron.common.runtime.vm.DataWord; +import org.tron.common.utils.ByteUtil; import org.tron.core.capsule.StorageRowCapsule; import org.tron.core.db.StorageRowStore; @@ -19,15 +20,25 @@ public class Storage { @Getter private final Map rowCache = new HashMap<>(); + @Getter + private byte[] address; + private static final int PREFIX_BYTES = 16; public Storage(byte[] address, StorageRowStore store) { addrHash = addrHash(address); + this.address = address; this.store = store; } + public void generateAddrHash(byte[] trxId) { + // update addreHash for create2 + addrHash = addrHash(address, trxId); + } + public Storage(Storage storage) { this.addrHash = storage.addrHash.clone(); + this.address = storage.getAddress().clone(); this.store = storage.store; storage.getRowCache().forEach((DataWord rowKey, StorageRowCapsule row) -> { StorageRowCapsule newRow = new StorageRowCapsule(row); @@ -70,6 +81,13 @@ private static byte[] addrHash(byte[] address) { return Hash.sha3(address); } + private static byte[] addrHash(byte[] address, byte[] trxHash) { + if (ByteUtil.isNullOrZeroArray(trxHash)) { + return Hash.sha3(address); + } + return Hash.sha3(ByteUtil.merge(address, trxHash)); + } + public void commit() { rowCache.forEach((DataWord rowKey, StorageRowCapsule row) -> { if (row.isDirty()) { diff --git a/src/main/java/org/tron/common/runtime/vm/program/invoke/ProgramInvokeMockImpl.java b/src/main/java/org/tron/common/runtime/vm/program/invoke/ProgramInvokeMockImpl.java index 771a85c305d..9f68412715a 100644 --- a/src/main/java/org/tron/common/runtime/vm/program/invoke/ProgramInvokeMockImpl.java +++ b/src/main/java/org/tron/common/runtime/vm/program/invoke/ProgramInvokeMockImpl.java @@ -15,8 +15,10 @@ * You should have received a copy of the GNU Lesser General Public License * along with the ethereumJ library. If not, see . */ + package org.tron.common.runtime.vm.program.invoke; +import com.google.protobuf.ByteString; import org.spongycastle.util.Arrays; import org.spongycastle.util.encoders.Hex; import org.tron.common.crypto.ECKey; @@ -26,11 +28,15 @@ import org.tron.common.storage.Deposit; import org.tron.common.storage.DepositImpl; import org.tron.core.capsule.BlockCapsule; +import org.tron.core.capsule.ContractCapsule; import org.tron.core.exception.StoreException; import org.tron.protos.Protocol; +import org.tron.protos.Protocol.SmartContract; /** + * . + * * @author Roman Mandeleil * @since 03.06.2014 */ @@ -57,6 +63,9 @@ public ProgramInvokeMockImpl() { this.deposit.createAccount(ownerAddress, Protocol.AccountType.Normal); this.deposit.createAccount(contractAddress, Protocol.AccountType.Contract); + this.deposit.createContract(contractAddress, + new ContractCapsule(SmartContract.newBuilder().setContractAddress( + ByteString.copyFrom(contractAddress)).build())); this.deposit.saveCode(contractAddress, Hex.decode("385E60076000396000605f556014600054601e60" + "205463abcddcba6040545b51602001600a525451" @@ -119,13 +128,11 @@ public DataWord getTokenId() { return null; } - /*****************/ - /*** msg data ***/ - /** - * ************* - */ + /****************. + /*** msg data **. + /***************. - /* CALLDATALOAD op */ + /* CALLDATALOAD op */ public DataWord getDataValue(DataWord indexData) { byte[] data = new byte[32]; diff --git a/src/main/java/org/tron/common/storage/Deposit.java b/src/main/java/org/tron/common/storage/Deposit.java index f99b306476e..4763d942872 100644 --- a/src/main/java/org/tron/common/storage/Deposit.java +++ b/src/main/java/org/tron/common/storage/Deposit.java @@ -38,9 +38,13 @@ public interface Deposit { ContractCapsule getContract(byte[] address); - void saveCode(byte[] codeHash, byte[] code); + void updateContract(byte[] address, ContractCapsule contractCapsule); - byte[] getCode(byte[] codeHash); + void updateAccount(byte[] address, AccountCapsule accountCapsule); + + void saveCode(byte[] address, byte[] code); + + byte[] getCode(byte[] address); void putStorageValue(byte[] address, DataWord key, DataWord value); diff --git a/src/main/java/org/tron/common/storage/DepositImpl.java b/src/main/java/org/tron/common/storage/DepositImpl.java index 7ae17e2935d..17da1d21b36 100644 --- a/src/main/java/org/tron/common/storage/DepositImpl.java +++ b/src/main/java/org/tron/common/storage/DepositImpl.java @@ -8,6 +8,7 @@ import lombok.extern.slf4j.Slf4j; import org.spongycastle.util.Strings; import org.spongycastle.util.encoders.Hex; +import org.tron.common.crypto.Hash; import org.tron.common.runtime.config.VMConfig; import org.tron.common.runtime.vm.DataWord; import org.tron.common.runtime.vm.program.Storage; @@ -251,6 +252,20 @@ public synchronized void createContract(byte[] address, ContractCapsule contract contractCache.put(key, value); } + @Override + public void updateContract(byte[] address, ContractCapsule contractCapsule) { + Key key = Key.create(address); + Value value = Value.create(contractCapsule.getData(), Type.VALUE_TYPE_DIRTY); + contractCache.put(key, value); + } + + @Override + public void updateAccount(byte[] address, AccountCapsule accountCapsule) { + Key key = Key.create(address); + Value value = Value.create(accountCapsule.getData(), Type.VALUE_TYPE_DIRTY); + accountCache.put(key, value); + } + @Override public synchronized ContractCapsule getContract(byte[] address) { Key key = Key.create(address); @@ -272,27 +287,34 @@ public synchronized ContractCapsule getContract(byte[] address) { } @Override - public synchronized void saveCode(byte[] codeHash, byte[] code) { - Key key = Key.create(codeHash); + public synchronized void saveCode(byte[] address, byte[] code) { + Key key = Key.create(address); Value value = Value.create(code, Type.VALUE_TYPE_CREATE); codeCache.put(key, value); + + if (VMConfig.allowTvmConstantinople()) { + ContractCapsule contract = getContract(address); + byte[] codeHash = Hash.sha3(code); + contract.setCodeHash(codeHash); + updateContract(address, contract); + } } @Override - public synchronized byte[] getCode(byte[] addr) { - Key key = Key.create(addr); + public synchronized byte[] getCode(byte[] address) { + Key key = Key.create(address); if (codeCache.containsKey(key)) { return codeCache.get(key).getCode().getData(); } byte[] code; if (parent != null) { - code = parent.getCode(addr); + code = parent.getCode(address); } else { - if (null == getCodeStore().get(addr)) { + if (null == getCodeStore().get(address)) { code = null; } else { - code = getCodeStore().get(addr).getData(); + code = getCodeStore().get(address).getData(); } } if (code != null) { @@ -307,11 +329,11 @@ public synchronized Storage getStorage(byte[] address) { if (storageCache.containsKey(key)) { return storageCache.get(key); } - Storage storage; if (this.parent != null) { Storage parentStorage = parent.getStorage(address); if (VMConfig.getEnergyLimitHardFork()) { + // deep copy storage = new Storage(parentStorage); } else { storage = parentStorage; @@ -319,6 +341,10 @@ public synchronized Storage getStorage(byte[] address) { } else { storage = new Storage(address, dbManager.getStorageRowStore()); } + ContractCapsule contract = getContract(address); + if (contract != null && !ByteUtil.isNullOrZeroArray(contract.getTrxHash())) { + storage.generateAddrHash(contract.getTrxHash()); + } return storage; } diff --git a/src/main/java/org/tron/common/storage/Key.java b/src/main/java/org/tron/common/storage/Key.java index 83324d3d2d2..1188acc2560 100644 --- a/src/main/java/org/tron/common/storage/Key.java +++ b/src/main/java/org/tron/common/storage/Key.java @@ -5,10 +5,6 @@ import java.util.Arrays; public class Key { - - private static int MAX_KEY_LENGTH = 32; - private static int MIN_KEY_LENGTH = 1; - /** * data could not be null */ @@ -60,10 +56,7 @@ public boolean equals(Object o) { } Key key = (Key) o; - if (Arrays.equals(key.getData(), this.data)) { - return true; - } - return false; + return Arrays.equals(key.getData(), this.data); } @Override diff --git a/src/main/java/org/tron/common/storage/Type.java b/src/main/java/org/tron/common/storage/Type.java index 8c74e198cbb..2b3007665b7 100644 --- a/src/main/java/org/tron/common/storage/Type.java +++ b/src/main/java/org/tron/common/storage/Type.java @@ -5,10 +5,10 @@ public class Type { /** * Default Mode : VALUE_TYPE_NORMAL */ - public static int VALUE_TYPE_NORMAL = 0; - public static int VALUE_TYPE_DIRTY = 1 << 0; - public static int VALUE_TYPE_CREATE = 1 << 1; - public static int VALUE_TYPE_UNKNOWN = 0xFFFFFFFC; + public static final int VALUE_TYPE_NORMAL = 0; + public static final int VALUE_TYPE_DIRTY = 1 << 0; + public static final int VALUE_TYPE_CREATE = 1 << 1; + public static final int VALUE_TYPE_UNKNOWN = 0xFFFFFFFC; protected int type = VALUE_TYPE_NORMAL; @@ -79,11 +79,7 @@ public int getType() { * @return */ public boolean isValidType(int type) { - if ((type & VALUE_TYPE_UNKNOWN) != VALUE_TYPE_NORMAL) { - return false; - } - - return true; + return (type & VALUE_TYPE_UNKNOWN) == VALUE_TYPE_NORMAL; } /** @@ -121,11 +117,7 @@ public boolean equals(Object obj) { } Type T = (Type) obj; - if (this.type != T.getType()) { - return false; - } - - return true; + return this.type == T.getType(); } @Override diff --git a/src/main/java/org/tron/common/storage/WriteOptionsWrapper.java b/src/main/java/org/tron/common/storage/WriteOptionsWrapper.java index 85d463940df..69c62f6320f 100644 --- a/src/main/java/org/tron/common/storage/WriteOptionsWrapper.java +++ b/src/main/java/org/tron/common/storage/WriteOptionsWrapper.java @@ -1,13 +1,13 @@ package org.tron.common.storage; -public class WriteOptionsWrapper { +import lombok.Getter; - public org.rocksdb.WriteOptions rocks = null; - public org.iq80.leveldb.WriteOptions level = null; +public class WriteOptionsWrapper { - private WriteOptionsWrapper() { - - } + @Getter + private org.rocksdb.WriteOptions rocks = null; + @Getter + private org.iq80.leveldb.WriteOptions level = null; public static WriteOptionsWrapper getInstance() { WriteOptionsWrapper wapper = new WriteOptionsWrapper(); @@ -16,7 +16,6 @@ public static WriteOptionsWrapper getInstance() { return wapper; } - public WriteOptionsWrapper sync(boolean bool) { this.level.sync(bool); this.rocks.setSync(bool); diff --git a/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java b/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java index 6741f979047..e2a3d4689f1 100644 --- a/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java +++ b/src/main/java/org/tron/common/storage/leveldb/LevelDbDataSourceImpl.java @@ -17,6 +17,7 @@ import static org.fusesource.leveldbjni.JniDBFactory.factory; +import com.google.common.base.Preconditions; import com.google.common.collect.Sets; import java.io.File; import java.io.IOException; @@ -35,6 +36,7 @@ import java.util.stream.StreamSupport; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.iq80.leveldb.CompressionType; import org.iq80.leveldb.DB; import org.iq80.leveldb.DBException; @@ -43,6 +45,7 @@ import org.iq80.leveldb.WriteBatch; import org.iq80.leveldb.WriteOptions; import org.tron.common.storage.DbSourceInter; +import org.tron.common.utils.ByteUtil; import org.tron.common.storage.WriteOptionsWrapper; import org.tron.common.utils.FileUtil; import org.tron.common.utils.PropUtil; @@ -54,9 +57,11 @@ public class LevelDbDataSourceImpl implements DbSourceInter, Iterable> { - String dataBaseName; - DB database; - boolean alive; + private static final String ENGINE = "ENGINE"; + + private String dataBaseName; + private DB database; + private boolean alive; private String parentName; private ReadWriteLock resetDbLock = new ReentrantReadWriteLock(); @@ -85,18 +90,12 @@ public boolean checkOrInitEngine() { return false; } - String engine = PropUtil.readProperty(enginePath, "ENGINE"); - if (engine.equals("")) { - if (!PropUtil.writeProperty(enginePath, "ENGINE", "LEVELDB")) { - return false; - } - } - engine = PropUtil.readProperty(enginePath, "ENGINE"); - if ("LEVELDB".equals(engine)) { - return true; - } else { + String engine = PropUtil.readProperty(enginePath, ENGINE); + if (StringUtils.isEmpty(engine) && !PropUtil.writeProperty(enginePath, ENGINE, "LEVELDB")) { return false; } + engine = PropUtil.readProperty(enginePath, ENGINE); + return "LEVELDB".equals(engine); } @Override @@ -113,9 +112,7 @@ public void initDB() { return; } - if (dataBaseName == null) { - throw new NullPointerException("no name set to the dbStore"); - } + Preconditions.checkNotNull(dataBaseName, "no name set to the dbStore"); Options dbOptions = Args.getInstance().getStorage().getOptionsByDbName(dataBaseName); @@ -244,7 +241,7 @@ public void putData(byte[] key, byte[] value) { public void putData(byte[] key, byte[] value, WriteOptionsWrapper options) { resetDbLock.readLock().lock(); try { - database.put(key, value, options.level); + database.put(key, value, options.getLevel()); } finally { resetDbLock.readLock().unlock(); } @@ -264,7 +261,7 @@ public void deleteData(byte[] key) { public void deleteData(byte[] key, WriteOptionsWrapper options) { resetDbLock.readLock().lock(); try { - database.delete(key, options.level); + database.delete(key, options.getLevel()); } finally { resetDbLock.readLock().unlock(); } @@ -391,6 +388,48 @@ public Set getValuesPrev(byte[] key, long limit) { } } + public Map getPrevious(byte[] key, long limit, int precision) { + if (limit <= 0 || key.length < precision) { + return Collections.emptyMap(); + } + resetDbLock.readLock().lock(); + try (DBIterator iterator = database.iterator()) { + Map result = new HashMap<>(); + long i = 0; + for (iterator.seekToFirst(); iterator.hasNext() && i++ < limit; iterator.next()) { + Entry entry = iterator.peekNext(); + + if (entry.getKey().length >= precision) { + if (ByteUtil.less(ByteUtil.parseBytes(key, 0, precision), + ByteUtil.parseBytes(entry.getKey(), 0, precision))) { + break; + } + result.put(entry.getKey(), entry.getValue()); + } + } + return result; + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + resetDbLock.readLock().unlock(); + } + } + + public Map getAll() { + resetDbLock.readLock().lock(); + try (DBIterator iterator = database.iterator()) { + Map result = new HashMap<>(); + for (iterator.seekToFirst(); iterator.hasNext(); iterator.next()) { + result.put(iterator.peekNext().getKey(), iterator.peekNext().getValue()); + } + return result; + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + resetDbLock.readLock().unlock(); + } + } + @Override public long getTotal() throws RuntimeException { resetDbLock.readLock().lock(); @@ -453,10 +492,10 @@ public void updateByBatch(Map rows) { public void updateByBatch(Map rows, WriteOptionsWrapper options) { resetDbLock.readLock().lock(); try { - updateByBatchInner(rows, options.level); + updateByBatchInner(rows, options.getLevel()); } catch (Exception e) { try { - updateByBatchInner(rows, options.level); + updateByBatchInner(rows, options.getLevel()); } catch (Exception e1) { throw new RuntimeException(e); } diff --git a/src/main/java/org/tron/common/storage/leveldb/RocksDbDataSourceImpl.java b/src/main/java/org/tron/common/storage/leveldb/RocksDbDataSourceImpl.java index 95f54ec7f17..47b37286e87 100644 --- a/src/main/java/org/tron/common/storage/leveldb/RocksDbDataSourceImpl.java +++ b/src/main/java/org/tron/common/storage/leveldb/RocksDbDataSourceImpl.java @@ -1,5 +1,6 @@ package org.tron.common.storage.leveldb; +import com.google.common.base.Preconditions; import com.google.common.collect.Sets; import java.io.File; import java.io.IOException; @@ -9,12 +10,15 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Map.Entry; import java.util.Objects; import java.util.Set; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.iq80.leveldb.DBIterator; +import org.apache.commons.lang3.StringUtils; import org.rocksdb.BlockBasedTableConfig; import org.rocksdb.BloomFilter; import org.rocksdb.Checkpoint; @@ -29,6 +33,7 @@ import org.tron.common.storage.DbSourceInter; import org.tron.common.storage.RocksDbSettings; import org.tron.common.storage.WriteOptionsWrapper; +import org.tron.common.utils.ByteUtil; import org.tron.common.utils.FileUtil; import org.tron.common.utils.PropUtil; import org.tron.core.db.common.iterator.RockStoreIterator; @@ -37,12 +42,13 @@ @NoArgsConstructor public class RocksDbDataSourceImpl implements DbSourceInter, Iterable> { + private static final String ENGINE = "ENGINE"; private String dataBaseName; private RocksDB database; private boolean alive; private String parentName; - ReadOptions readOpts; + private ReadOptions readOpts; private ReadWriteLock resetDbLock = new ReentrantReadWriteLock(); @@ -153,18 +159,12 @@ public boolean checkOrInitEngine() { } // for the first init engine - String engine = PropUtil.readProperty(enginePath, "ENGINE"); - if (engine.equals("")) { - if (!PropUtil.writeProperty(enginePath, "ENGINE", "ROCKSDB")) { - return false; - } - } - engine = PropUtil.readProperty(enginePath, "ENGINE"); - if ("ROCKSDB".equals(engine)) { - return true; - } else { + String engine = PropUtil.readProperty(enginePath, ENGINE); + if (StringUtils.isEmpty(engine) && !PropUtil.writeProperty(enginePath, ENGINE, "ROCKSDB")) { return false; } + engine = PropUtil.readProperty(enginePath, ENGINE); + return "ROCKSDB".equals(engine); } public void initDB() { @@ -181,9 +181,8 @@ public void initDB(RocksDbSettings settings) { if (isAlive()) { return; } - if (dataBaseName == null) { - throw new NullPointerException("no name set to the dbStore"); - } + + Preconditions.checkNotNull(dataBaseName, "no name set to the dbStore"); try (Options options = new Options()) { @@ -259,7 +258,7 @@ public void putData(byte[] key, byte[] value) { try { database.put(key, value); } catch (RocksDBException e) { - logger.error("RocksDBException:{}", e); + logger.error(e.getMessage(), e); } finally { resetDbLock.readLock().unlock(); } @@ -272,9 +271,9 @@ public void putData(byte[] key, byte[] value, WriteOptionsWrapper optionsWrapper } resetDbLock.readLock().lock(); try { - database.put(optionsWrapper.rocks, key, value); + database.put(optionsWrapper.getRocks(), key, value); } catch (RocksDBException e) { - logger.error("RocksDBException:{}", e); + logger.error(e.getMessage(), e); } finally { resetDbLock.readLock().unlock(); } @@ -289,7 +288,7 @@ public byte[] getData(byte[] key) { try { return database.get(key); } catch (RocksDBException e) { - logger.error("RocksDBException: {}", e); + logger.error(e.getMessage(), e); } finally { resetDbLock.readLock().unlock(); } @@ -305,7 +304,7 @@ public void deleteData(byte[] key) { try { database.delete(key); } catch (RocksDBException e) { - logger.error("RocksDBException:{}", e); + logger.error(e.getMessage(), e); } finally { resetDbLock.readLock().unlock(); } @@ -318,9 +317,9 @@ public void deleteData(byte[] key, WriteOptionsWrapper optionsWrapper) { } resetDbLock.readLock().lock(); try { - database.delete(optionsWrapper.rocks, key); + database.delete(optionsWrapper.getRocks(), key); } catch (RocksDBException e) { - logger.error("RocksDBException:{}", e); + logger.error(e.getMessage(), e); } finally { resetDbLock.readLock().unlock(); } @@ -395,7 +394,7 @@ public void updateByBatch(Map rows, WriteOptionsWrapper optionsW } resetDbLock.readLock().lock(); try { - updateByBatchInner(rows, optionsWrapper.rocks); + updateByBatchInner(rows, optionsWrapper.getRocks()); } catch (Exception e) { try { updateByBatchInner(rows); @@ -492,6 +491,33 @@ public Set getValuesNext(byte[] key, long limit) { } } + public Map getPrevious(byte[] key, long limit, int precision) { + if (quitIfNotAlive()) { + return null; + } + if (limit <= 0 || key.length < precision) { + return Collections.emptyMap(); + } + resetDbLock.readLock().lock(); + try (RocksIterator iterator = database.newIterator()) { + Map result = new HashMap<>(); + long i = 0; + for (iterator.seekToFirst(); iterator.isValid() && i++ < limit; iterator.next()) { + + if (iterator.key().length >= precision) { + if (ByteUtil.less(ByteUtil.parseBytes(key, 0, precision), + ByteUtil.parseBytes(iterator.key(), 0, precision))) { + break; + } + result.put(iterator.key(), iterator.value()); + } + } + return result; + } finally { + resetDbLock.readLock().unlock(); + } + } + public void backup(String dir) throws RocksDBException { Checkpoint cp = Checkpoint.create(database); cp.createCheckpoint(dir + this.getDBName()); diff --git a/src/main/java/org/tron/common/utils/ByteArrayMap.java b/src/main/java/org/tron/common/utils/ByteArrayMap.java index 1779b23238c..5028e7dd8fb 100644 --- a/src/main/java/org/tron/common/utils/ByteArrayMap.java +++ b/src/main/java/org/tron/common/utils/ByteArrayMap.java @@ -30,6 +30,7 @@ public class ByteArrayMap implements Map { + private static final String RUNTIME_EXCEPTION_MSG = "Not implemented"; private final Map delegate; @@ -138,7 +139,7 @@ public boolean isEmpty() { @Override public boolean contains(Object o) { - throw new RuntimeException("Not implemented"); + throw new RuntimeException(RUNTIME_EXCEPTION_MSG); } @Override @@ -166,47 +167,47 @@ public void remove() { @Override public Object[] toArray() { - throw new RuntimeException("Not implemented"); + throw new RuntimeException(RUNTIME_EXCEPTION_MSG); } @Override public T[] toArray(T[] a) { - throw new RuntimeException("Not implemented"); + throw new RuntimeException(RUNTIME_EXCEPTION_MSG); } @Override public boolean add(Entry vEntry) { - throw new RuntimeException("Not implemented"); + throw new RuntimeException(RUNTIME_EXCEPTION_MSG); } @Override public boolean remove(Object o) { - throw new RuntimeException("Not implemented"); + throw new RuntimeException(RUNTIME_EXCEPTION_MSG); } @Override public boolean containsAll(Collection c) { - throw new RuntimeException("Not implemented"); + throw new RuntimeException(RUNTIME_EXCEPTION_MSG); } @Override public boolean addAll(Collection> c) { - throw new RuntimeException("Not implemented"); + throw new RuntimeException(RUNTIME_EXCEPTION_MSG); } @Override public boolean retainAll(Collection c) { - throw new RuntimeException("Not implemented"); + throw new RuntimeException(RUNTIME_EXCEPTION_MSG); } @Override public boolean removeAll(Collection c) { - throw new RuntimeException("Not implemented"); + throw new RuntimeException(RUNTIME_EXCEPTION_MSG); } @Override public void clear() { - throw new RuntimeException("Not implemented"); + throw new RuntimeException(RUNTIME_EXCEPTION_MSG); } } diff --git a/src/main/java/org/tron/common/utils/ByteArraySet.java b/src/main/java/org/tron/common/utils/ByteArraySet.java index d11de69dfb0..6243eba9725 100644 --- a/src/main/java/org/tron/common/utils/ByteArraySet.java +++ b/src/main/java/org/tron/common/utils/ByteArraySet.java @@ -27,6 +27,7 @@ public class ByteArraySet implements Set { + private static final String RUNTIME_EXCEPTION_MSG = "Not implemented"; private Set delegate; @@ -104,7 +105,7 @@ public boolean remove(Object o) { @Override public boolean containsAll(Collection c) { - throw new RuntimeException("Not implemented"); + throw new RuntimeException(RUNTIME_EXCEPTION_MSG); } @Override @@ -118,12 +119,12 @@ public boolean addAll(Collection c) { @Override public boolean retainAll(Collection c) { - throw new RuntimeException("Not implemented"); + throw new RuntimeException(RUNTIME_EXCEPTION_MSG); } @Override public boolean removeAll(Collection c) { - throw new RuntimeException("Not implemented"); + throw new RuntimeException(RUNTIME_EXCEPTION_MSG); } @Override @@ -133,11 +134,11 @@ public void clear() { @Override public boolean equals(Object o) { - throw new RuntimeException("Not implemented"); + throw new RuntimeException(RUNTIME_EXCEPTION_MSG); } @Override public int hashCode() { - throw new RuntimeException("Not implemented"); + throw new RuntimeException(RUNTIME_EXCEPTION_MSG); } } diff --git a/src/main/java/org/tron/common/utils/ByteUtil.java b/src/main/java/org/tron/common/utils/ByteUtil.java index 588ab371ba2..00bbad84683 100644 --- a/src/main/java/org/tron/common/utils/ByteUtil.java +++ b/src/main/java/org/tron/common/utils/ByteUtil.java @@ -367,6 +367,10 @@ public static boolean equals(byte[] bytes1, byte[] bytes2) { return compare(bytes1, bytes2) == 0; } + public static boolean isNullOrZeroArray(byte[] array){ + return (array == null) || (array.length == 0); + } + // lexicographical order public static int compare(byte[] bytes1, byte[] bytes2) { Preconditions.checkNotNull(bytes1); diff --git a/src/main/java/org/tron/common/utils/ExecutorLoop.java b/src/main/java/org/tron/common/utils/ExecutorLoop.java deleted file mode 100644 index 6d4e7c71bc9..00000000000 --- a/src/main/java/org/tron/common/utils/ExecutorLoop.java +++ /dev/null @@ -1,104 +0,0 @@ -package org.tron.common.utils; - -import java.util.List; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Consumer; - -public class ExecutorLoop { - - private BlockingQueue queue; - private ThreadPoolExecutor exec; - private Consumer consumer; - private Consumer exceptionHandler; - private String threadPoolName; - - private static AtomicInteger loopNum = new AtomicInteger(1); - private AtomicInteger threadNumber = new AtomicInteger(1); - - public ExecutorLoop( - int threads, - int queueSize, - Consumer consumer, - Consumer exceptionHandler) { - - this.queue = new LimitedQueue<>(queueSize); - this.exec = new ThreadPoolExecutor( - threads, - threads, - 0L, - TimeUnit.MILLISECONDS, - queue, - r -> new Thread(r, threadPoolName + "-" + threadNumber.getAndIncrement()) - ); - - this.consumer = consumer; - this.exceptionHandler = exceptionHandler; - this.threadPoolName = "loop-" + loopNum.getAndIncrement(); - } - - public void push(final In in) { - exec.execute(() -> { - try { - consumer.accept(in); - } catch (Throwable e) { - exceptionHandler.accept(e); - } - }); - } - - public void pushAll(final List list) { - for (In in : list) { - push(in); - } - } - - public ExecutorLoop setThreadPoolName(String threadPoolName) { - this.threadPoolName = threadPoolName; - return this; - } - - public BlockingQueue getQueue() { - return queue; - } - - - public void shutdown() { - try { - exec.shutdown(); - } catch (Exception e) { - } - } - - public boolean isShutdown() { - return exec.isShutdown(); - } - - public void join() throws InterruptedException { - exec.shutdown(); - exec.awaitTermination(10, TimeUnit.MINUTES); - } - - private static class LimitedQueue extends LinkedBlockingQueue { - - public LimitedQueue(int maxSize) { - super(maxSize); - } - - @Override - public boolean offer(E e) { - // turn offer() and add() into a blocking calls (unless interrupted) - try { - put(e); - return true; - } catch (InterruptedException ie) { - Thread.currentThread().interrupt(); - } - return false; - } - } -} - diff --git a/src/main/java/org/tron/common/utils/FastByteComparisons.java b/src/main/java/org/tron/common/utils/FastByteComparisons.java index 2425b690c9a..3378482c05f 100644 --- a/src/main/java/org/tron/common/utils/FastByteComparisons.java +++ b/src/main/java/org/tron/common/utils/FastByteComparisons.java @@ -79,11 +79,11 @@ int compareTo(T buffer1, int offset1, int length1, */ private static class LexicographicalComparerHolder { - static final String UNSAFE_COMPARER_NAME = + private static final String UNSAFE_COMPARER_NAME = LexicographicalComparerHolder.class.getName() + "$UnsafeComparer"; - static final Comparer BEST_COMPARER = getBestComparer(); + private static final Comparer BEST_COMPARER = getBestComparer(); /** * Returns the Unsafe-using Comparer, or falls back to the pure-Java implementation if unable to diff --git a/src/main/java/org/tron/common/utils/FileUtil.java b/src/main/java/org/tron/common/utils/FileUtil.java index 5fb4ca65941..22fd31e1e5d 100755 --- a/src/main/java/org/tron/common/utils/FileUtil.java +++ b/src/main/java/org/tron/common/utils/FileUtil.java @@ -77,7 +77,10 @@ public static boolean recursiveDelete(String fileName) { .forEachOrdered(FileUtil::recursiveDelete); } - file.setWritable(true); + if (!file.setWritable(true)){ + logger.warn("failed to setWritable: " + fileName); + } + return file.delete(); } return false; @@ -86,7 +89,11 @@ public static boolean recursiveDelete(String fileName) { public static void saveData(String filePath, String data, boolean append) { File priFile = new File(filePath); try { - priFile.createNewFile(); + if (!priFile.createNewFile()){ + logger.warn("failed to create new file: " + filePath); + return; + } + try (BufferedWriter bw = new BufferedWriter(new FileWriter(priFile, append))) { bw.write(data); bw.flush(); @@ -102,7 +109,7 @@ public static int readData(String filePath, char[] buf) { try (BufferedReader bufRead = new BufferedReader(new FileReader(file))) { len = bufRead.read(buf, 0, buf.length); } catch (IOException ex) { - ex.printStackTrace(); + logger.warn(ex.getMessage()); return 0; } return len; @@ -129,7 +136,9 @@ public static boolean createFileIfNotExists(String filepath) { File file = new File(filepath); if (!file.exists()) { try { - file.createNewFile(); + if (!file.createNewFile()){ + logger.warn("failed to create new file" + filepath); + } } catch (Exception e) { return false; } diff --git a/src/main/java/org/tron/common/utils/PropUtil.java b/src/main/java/org/tron/common/utils/PropUtil.java index a82224c1338..57c62ff41e6 100644 --- a/src/main/java/org/tron/common/utils/PropUtil.java +++ b/src/main/java/org/tron/common/utils/PropUtil.java @@ -1,11 +1,12 @@ package org.tron.common.utils; +import static java.nio.charset.StandardCharsets.UTF_8; + import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileInputStream; import java.io.FileOutputStream; -import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; @@ -19,7 +20,7 @@ public class PropUtil { public static String readProperty(String file, String key) { InputStream is = null; FileInputStream fis = null; - Properties prop = null; + Properties prop; try { prop = new Properties(); fis = new FileInputStream(file); @@ -31,23 +32,17 @@ public static String readProperty(String file, String key) { logger.error("{}", e); return ""; } finally { - if (prop != null) { - prop = null; - } - //fis try { if (fis != null) { fis.close(); - fis = null; } } catch (Exception e) { logger.warn("{}", e); } - //is + try { if (is != null) { is.close(); - is = null; } } catch (Exception e) { logger.error("{}", e); @@ -56,42 +51,58 @@ public static String readProperty(String file, String key) { } public static boolean writeProperty(String file, String key, String value) { - FileInputStream fis = null; - Properties properties = new Properties(); + FileInputStream in = null; OutputStream out = null; + BufferedReader br = null; + BufferedWriter bw = null; + Properties properties = new Properties(); + try { - fis = new FileInputStream(file); - BufferedReader bf = new BufferedReader(new InputStreamReader(fis, "UTF-8")); - properties.load(bf); + in = new FileInputStream(file); + br = new BufferedReader(new InputStreamReader(in, UTF_8)); + properties.load(br); out = new FileOutputStream(file); - BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out, "UTF-8")); + bw = new BufferedWriter(new OutputStreamWriter(out, UTF_8)); properties.setProperty(key, value); properties.store(bw, "Generated by the application. PLEASE DO NOT EDIT! "); + return true; } catch (Exception e) { logger.warn("{}", e); return false; } finally { - if (properties != null) { - properties = null; + try { + if (in != null) { + in.close(); + } + } catch (Exception e) { + logger.warn("{}", e); } - //fis + try { - if (fis != null) { - fis.close(); - fis = null; + if (br != null) { + br.close(); + } + } catch (Exception e) { + logger.warn("{}", e); + } + + try { + if (out != null) { + out.close(); } } catch (Exception e) { logger.warn("{}", e); } - //out + try { - out.close(); - out = null; - } catch (IOException e) { + if (bw != null) { + bw.close(); + } + } catch (Exception e) { logger.warn("{}", e); } } - return true; + } } \ No newline at end of file diff --git a/src/main/java/org/tron/core/Constant.java b/src/main/java/org/tron/core/Constant.java index bfc4fffff2a..5cbe5ad0a60 100644 --- a/src/main/java/org/tron/core/Constant.java +++ b/src/main/java/org/tron/core/Constant.java @@ -45,7 +45,6 @@ public class Constant { public static final long TRANSACTION_MAX_BYTE_SIZE = 500 * 1_024L; public static final long MAXIMUM_TIME_UNTIL_EXPIRATION = 24 * 60 * 60 * 1_000L; //one day public static final long TRANSACTION_DEFAULT_EXPIRATION_TIME = 60 * 1_000L; //60 seconds - // config for smart contract public static final long SUN_PER_ENERGY = 100; // 1 us = 100 DROP = 100 * 10^-6 TRX public static final long ENERGY_LIMIT_IN_CONSTANT_TX = 3_000_000L; // ref: 1 us = 1 energy @@ -58,4 +57,13 @@ public class Constant { public static final int ONE_HUNDRED = 100; public static final int ONE_THOUSAND = 1000; + + /** + * normal transaction is 0 representing normal transaction + * unexecuted deferred transaction is 1 representing unexecuted deferred transaction + * executing deferred transaction is 2 representing executing deferred transaction + */ + public static final int NORMALTRANSACTION = 0; + public static final int UNEXECUTEDDEFERREDTRANSACTION = 1; + public static final int EXECUTINGDEFERREDTRANSACTION = 2; } diff --git a/src/main/java/org/tron/core/Wallet.java b/src/main/java/org/tron/core/Wallet.java index ecb21968a4d..5c72ca06355 100755 --- a/src/main/java/org/tron/core/Wallet.java +++ b/src/main/java/org/tron/core/Wallet.java @@ -75,6 +75,7 @@ import org.tron.common.storage.DepositImpl; import org.tron.common.utils.Base58; import org.tron.common.utils.ByteArray; +import org.tron.common.utils.ByteUtil; import org.tron.common.utils.Sha256Hash; import org.tron.common.utils.Utils; import org.tron.core.actuator.Actuator; @@ -92,6 +93,7 @@ import org.tron.core.capsule.TransactionInfoCapsule; import org.tron.core.capsule.TransactionResultCapsule; import org.tron.core.capsule.WitnessCapsule; +import org.tron.core.capsule.utils.TransactionUtil; import org.tron.core.config.Parameter.ChainConstant; import org.tron.core.config.args.Args; import org.tron.core.db.AccountIdIndexStore; @@ -153,7 +155,7 @@ public class Wallet { private Manager dbManager; @Autowired private NodeManager nodeManager; - private static String addressPreFixString = Constant.ADD_PRE_FIX_STRING_MAINNET; //default testnet + private static String addressPreFixString = Constant.ADD_PRE_FIX_STRING_MAINNET;//default testnet private static byte addressPreFixByte = Constant.ADD_PRE_FIX_BYTE_MAINNET; private int minEffectiveConnection = Args.getInstance().getMinEffectiveConnection(); @@ -282,6 +284,13 @@ public static byte[] generateContractAddress(byte[] ownerAddress, byte[] txRawDa } + // for `CREATE2` + public static byte[] generateContractAddress2(byte[] address, byte[] salt, byte[] code) { + byte[] mergedData = ByteUtil.merge(address, salt, Hash.sha3(code)); + return Hash.sha3omit12(mergedData); + } + + // for `CREATE` public static byte[] generateContractAddress(byte[] transactionRootId, long nonce) { byte[] nonceBytes = Longs.toByteArray(nonce); byte[] combined = new byte[transactionRootId.length + nonceBytes.length]; @@ -415,9 +424,8 @@ public TransactionCapsule createTransactionCapsule(com.google.protobuf.Message m public GrpcAPI.Return broadcastTransaction(Transaction signaturedTransaction) { GrpcAPI.Return.Builder builder = GrpcAPI.Return.newBuilder(); TransactionCapsule trx = new TransactionCapsule(signaturedTransaction); - Message message = new TransactionMessage(signaturedTransaction); - try { + Message message = new TransactionMessage(signaturedTransaction.toByteArray()); if (minEffectiveConnection != 0) { if (tronNetDelegate.getActivePeer().isEmpty()) { logger.warn("Broadcast transaction {} failed, no connection.", trx.getTransactionId()); @@ -892,6 +900,28 @@ public Protocol.ChainParameters getChainParameters() { .setValue(dbManager.getDynamicPropertiesStore().getMultiSignFee()) .build()); + builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() + .setKey("getUpdateAccountPermissionFee") + .setValue(dbManager.getDynamicPropertiesStore().getUpdateAccountPermissionFee()) + .build()); + + builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() + .setKey("getAllowAccountStateRoot") + .setValue(dbManager.getDynamicPropertiesStore().getAllowAccountStateRoot()) + .build()); + + builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() + .setKey("getAllowProtoFilterNum") + .setValue(dbManager.getDynamicPropertiesStore().getAllowProtoFilterNum()) + .build()); + + // ALLOW_TVM_CONSTANTINOPLE, // 1, 30 + builder.addChainParameter( + Protocol.ChainParameters.ChainParameter.newBuilder() + .setKey("getAllowTvmConstantinople") + .setValue(dbManager.getDynamicPropertiesStore().getAllowTvmConstantinople()) + .build()); + return builder.build(); } @@ -1149,13 +1179,13 @@ public NumberMessage getNextMaintenanceTime() { return builder.build(); } - public Block getBlockById(ByteString BlockId) { - if (Objects.isNull(BlockId)) { + public Block getBlockById(ByteString blockId) { + if (Objects.isNull(blockId)) { return null; } Block block = null; try { - block = dbManager.getBlockStore().get(BlockId.toByteArray()).getInstance(); + block = dbManager.getBlockStore().get(blockId.toByteArray()).getInstance(); } catch (StoreException e) { } return block; @@ -1187,6 +1217,7 @@ public Transaction getTransactionById(ByteString transactionId) { transactionCapsule = dbManager.getTransactionStore() .get(transactionId.toByteArray()); } catch (StoreException e) { + return null; } if (transactionCapsule != null) { return transactionCapsule.getInstance(); @@ -1203,6 +1234,7 @@ public TransactionInfo getTransactionInfoById(ByteString transactionId) { transactionInfoCapsule = dbManager.getTransactionHistoryStore() .get(transactionId.toByteArray()); } catch (StoreException e) { + return null; } if (transactionInfoCapsule != null) { return transactionInfoCapsule.getInstance(); @@ -1234,6 +1266,7 @@ public Exchange getExchangeById(ByteString exchangeId) { try { exchangeCapsule = dbManager.getExchangeStoreFinal().get(exchangeId.toByteArray()); } catch (StoreException e) { + return null; } if (exchangeCapsule != null) { return exchangeCapsule.getInstance(); @@ -1286,50 +1319,81 @@ public Transaction triggerContract(TriggerSmartContract triggerSmartContract, byte[] selector = getSelector(triggerSmartContract.getData().toByteArray()); - if (!isConstant(abi, selector)) { - return trxCap.getInstance(); + if (isConstant(abi, selector)) { + return callConstantContract(trxCap, builder, retBuilder); } else { - if (!Args.getInstance().isSupportConstant()) { - throw new ContractValidateException("this node don't support constant"); - } - DepositImpl deposit = DepositImpl.createRoot(dbManager); + return trxCap.getInstance(); + } + } - Block headBlock; - List blockCapsuleList = dbManager.getBlockStore().getBlockByLatestNum(1); - if (CollectionUtils.isEmpty(blockCapsuleList)) { - throw new HeaderNotFound("latest block not found"); - } else { - headBlock = blockCapsuleList.get(0).getInstance(); - } + public Transaction triggerConstantContract(TriggerSmartContract triggerSmartContract, + TransactionCapsule trxCap, Builder builder, + Return.Builder retBuilder) + throws ContractValidateException, ContractExeException, HeaderNotFound, VMIllegalException { - Runtime runtime = new RuntimeImpl(trxCap.getInstance(), new BlockCapsule(headBlock), deposit, - new ProgramInvokeFactoryImpl(), true); - VMConfig.initVmHardFork(); - VMConfig.initAllowTvmTransferTrc10( - dbManager.getDynamicPropertiesStore().getAllowTvmTransferTrc10()); - VMConfig.initAllowMultiSign(dbManager.getDynamicPropertiesStore().getAllowMultiSign()); - runtime.execute(); - runtime.go(); - runtime.finalization(); - // TODO exception - if (runtime.getResult().getException() != null) { - RuntimeException e = runtime.getResult().getException(); - logger.warn("Constant call has error {}", e.getMessage()); - throw e; - } + ContractStore contractStore = dbManager.getContractStore(); + byte[] contractAddress = triggerSmartContract.getContractAddress().toByteArray(); + byte[] isContractExiste = contractStore.findContractByHash(contractAddress); + + if (ArrayUtils.isEmpty(isContractExiste)) { + throw new ContractValidateException("No contract or not a smart contract"); + } - ProgramResult result = runtime.getResult(); - TransactionResultCapsule ret = new TransactionResultCapsule(); + if (!Args.getInstance().isSupportConstant()) { + throw new ContractValidateException("this node don't support constant"); + } - builder.addConstantResult(ByteString.copyFrom(result.getHReturn())); - ret.setStatus(0, code.SUCESS); - if (StringUtils.isNoneEmpty(runtime.getRuntimeError())) { - ret.setStatus(0, code.FAILED); - retBuilder.setMessage(ByteString.copyFromUtf8(runtime.getRuntimeError())).build(); - } - trxCap.setResult(ret); - return trxCap.getInstance(); + return callConstantContract(trxCap, builder, retBuilder); + } + + public Transaction callConstantContract(TransactionCapsule trxCap, Builder builder, + Return.Builder retBuilder) + throws ContractValidateException, ContractExeException, HeaderNotFound, VMIllegalException { + + if (!Args.getInstance().isSupportConstant()) { + throw new ContractValidateException("this node don't support constant"); + } + DepositImpl deposit = DepositImpl.createRoot(dbManager); + + Block headBlock; + List blockCapsuleList = dbManager.getBlockStore().getBlockByLatestNum(1); + if (CollectionUtils.isEmpty(blockCapsuleList)) { + throw new HeaderNotFound("latest block not found"); + } else { + headBlock = blockCapsuleList.get(0).getInstance(); + } + + Runtime runtime = new RuntimeImpl(trxCap.getInstance(), new BlockCapsule(headBlock), deposit, + new ProgramInvokeFactoryImpl(), true); + VMConfig.initVmHardFork(); + VMConfig.initAllowTvmTransferTrc10( + dbManager.getDynamicPropertiesStore().getAllowTvmTransferTrc10()); + VMConfig.initAllowMultiSign(dbManager.getDynamicPropertiesStore().getAllowMultiSign()); + runtime.execute(); + runtime.go(); + runtime.finalization(); + // TODO exception + if (runtime.getResult().getException() != null) { + RuntimeException e = runtime.getResult().getException(); + logger.warn("Constant call has error {}", e.getMessage()); + throw e; } + + ProgramResult result = runtime.getResult(); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + builder.addConstantResult(ByteString.copyFrom(result.getHReturn())); + ret.setStatus(0, code.SUCESS); + if (StringUtils.isNoneEmpty(runtime.getRuntimeError())) { + ret.setStatus(0, code.FAILED); + retBuilder.setMessage(ByteString.copyFromUtf8(runtime.getRuntimeError())).build(); + } + if (runtime.getResult().isRevert()) { + ret.setStatus(0, code.FAILED); + retBuilder.setMessage(ByteString.copyFromUtf8("REVERT opcode executed")).build(); + } + trxCap.setResult(ret); + return trxCap.getInstance(); } public SmartContract getContract(GrpcAPI.BytesMessage bytesMessage) { diff --git a/src/main/java/org/tron/core/actuator/AccountPermissionUpdateActuator.java b/src/main/java/org/tron/core/actuator/AccountPermissionUpdateActuator.java index a6bee5cc8e6..1f67cda5694 100644 --- a/src/main/java/org/tron/core/actuator/AccountPermissionUpdateActuator.java +++ b/src/main/java/org/tron/core/actuator/AccountPermissionUpdateActuator.java @@ -130,7 +130,7 @@ private boolean checkPermission(Permission permission) throws ContractValidateEx byte[] types1 = dbManager.getDynamicPropertiesStore().getAvailableContractType(); for (int i = 0; i < 256; i++) { boolean b = (operations.byteAt(i / 8) & (1 << (i % 8))) != 0; - boolean t = (types1[(i / 8)] & (1 << (i % 8))) != 0; + boolean t = ((types1[(i / 8)] & 0xff) & (1 << (i % 8))) != 0; if (b && !t) { throw new ContractValidateException(i + " isn't a validate ContractType"); } diff --git a/src/main/java/org/tron/core/actuator/ActuatorFactory.java b/src/main/java/org/tron/core/actuator/ActuatorFactory.java index 2407a666539..056e6e34396 100644 --- a/src/main/java/org/tron/core/actuator/ActuatorFactory.java +++ b/src/main/java/org/tron/core/actuator/ActuatorFactory.java @@ -89,6 +89,8 @@ private static Actuator getActuatorByContract(Contract contract, Manager manager return new UpdateSettingContractActuator(contract.getParameter(), manager); case UpdateEnergyLimitContract: return new UpdateEnergyLimitContractActuator(contract.getParameter(), manager); + case ClearABIContract: + return new ClearABIContractActuator(contract.getParameter(), manager); case ExchangeCreateContract: return new ExchangeCreateActuator(contract.getParameter(), manager); case ExchangeInjectContract: diff --git a/src/main/java/org/tron/core/actuator/ClearABIContractActuator.java b/src/main/java/org/tron/core/actuator/ClearABIContractActuator.java new file mode 100755 index 00000000000..d7bad74dbf7 --- /dev/null +++ b/src/main/java/org/tron/core/actuator/ClearABIContractActuator.java @@ -0,0 +1,118 @@ +package org.tron.core.actuator; + +import com.google.protobuf.Any; +import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; +import java.util.Arrays; +import lombok.extern.slf4j.Slf4j; +import org.tron.common.runtime.config.VMConfig; +import org.tron.common.utils.StringUtil; +import org.tron.core.Wallet; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.ContractCapsule; +import org.tron.core.capsule.TransactionResultCapsule; +import org.tron.core.db.AccountStore; +import org.tron.core.db.Manager; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; +import org.tron.protos.Contract.ClearABIContract; +import org.tron.protos.Protocol.Transaction.Result.code; + +@Slf4j(topic = "actuator") +public class ClearABIContractActuator extends AbstractActuator { + + ClearABIContractActuator(Any contract, Manager dbManager) { + super(contract, dbManager); + } + + @Override + public boolean execute(TransactionResultCapsule ret) throws ContractExeException { + long fee = calcFee(); + try { + ClearABIContract usContract = contract.unpack(ClearABIContract.class); + + byte[] contractAddress = usContract.getContractAddress().toByteArray(); + ContractCapsule deployedContract = dbManager.getContractStore().get(contractAddress); + + deployedContract.clearABI(); + dbManager.getContractStore().put(contractAddress, deployedContract); + + ret.setStatus(fee, code.SUCESS); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + ret.setStatus(fee, code.FAILED); + throw new ContractExeException(e.getMessage()); + } + return true; + } + + @Override + public boolean validate() throws ContractValidateException { + if (!VMConfig.allowTvmConstantinople()) { + throw new ContractValidateException( + "contract type error,unexpected type [ClearABIContract]"); + } + + if (this.contract == null) { + throw new ContractValidateException("No contract!"); + } + if (this.dbManager == null) { + throw new ContractValidateException("No dbManager!"); + } + if (!this.contract.is(ClearABIContract.class)) { + throw new ContractValidateException( + "contract type error,expected type [ClearABIContract],real type[" + + contract + .getClass() + "]"); + } + final ClearABIContract contract; + try { + contract = this.contract.unpack(ClearABIContract.class); + } catch (InvalidProtocolBufferException e) { + logger.debug(e.getMessage(), e); + throw new ContractValidateException(e.getMessage()); + } + if (!Wallet.addressValid(contract.getOwnerAddress().toByteArray())) { + throw new ContractValidateException("Invalid address"); + } + byte[] ownerAddress = contract.getOwnerAddress().toByteArray(); + String readableOwnerAddress = StringUtil.createReadableString(ownerAddress); + + AccountStore accountStore = dbManager.getAccountStore(); + + AccountCapsule accountCapsule = accountStore.get(ownerAddress); + if (accountCapsule == null) { + throw new ContractValidateException( + "Account[" + readableOwnerAddress + "] not exists"); + } + + byte[] contractAddress = contract.getContractAddress().toByteArray(); + ContractCapsule deployedContract = dbManager.getContractStore().get(contractAddress); + + if (deployedContract == null) { + throw new ContractValidateException( + "Contract not exists"); + } + + byte[] deployedContractOwnerAddress = deployedContract.getInstance().getOriginAddress() + .toByteArray(); + + if (!Arrays.equals(ownerAddress, deployedContractOwnerAddress)) { + throw new ContractValidateException( + "Account[" + readableOwnerAddress + "] is not the owner of the contract"); + } + + return true; + } + + @Override + public ByteString getOwnerAddress() throws InvalidProtocolBufferException { + return contract.unpack(ClearABIContract.class).getOwnerAddress(); + } + + @Override + public long calcFee() { + return 0; + } + +} diff --git a/src/main/java/org/tron/core/actuator/ExchangeInjectActuator.java b/src/main/java/org/tron/core/actuator/ExchangeInjectActuator.java index 7b883413a62..70b6e6ffe9f 100755 --- a/src/main/java/org/tron/core/actuator/ExchangeInjectActuator.java +++ b/src/main/java/org/tron/core/actuator/ExchangeInjectActuator.java @@ -39,7 +39,6 @@ public boolean execute(TransactionResultCapsule ret) throws ContractExeException ExchangeCapsule exchangeCapsule; exchangeCapsule = dbManager.getExchangeStoreFinal(). get(ByteArray.fromLong(exchangeInjectContract.getExchangeId())); - byte[] firstTokenID = exchangeCapsule.getFirstTokenId(); byte[] secondTokenID = exchangeCapsule.getSecondTokenId(); long firstTokenBalance = exchangeCapsule.getFirstTokenBalance(); diff --git a/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java b/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java index c80d1c9646a..c429d363162 100755 --- a/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java +++ b/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java @@ -18,6 +18,7 @@ import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.protos.Contract.FreezeBalanceContract; +import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Transaction.Result.code; @Slf4j(topic = "actuator") @@ -189,6 +190,13 @@ public boolean validate() throws ContractValidateException { "Account[" + readableOwnerAddress + "] not exists"); } + if (dbManager.getDynamicPropertiesStore().getAllowTvmConstantinople() == 1 + && receiverCapsule.getType() == AccountType.Contract) { + throw new ContractValidateException( + "Do not allow delegate resources to contract addresses"); + + } + } return true; diff --git a/src/main/java/org/tron/core/actuator/ProposalApproveActuator.java b/src/main/java/org/tron/core/actuator/ProposalApproveActuator.java index 43e523f98d7..1cb06324bbf 100755 --- a/src/main/java/org/tron/core/actuator/ProposalApproveActuator.java +++ b/src/main/java/org/tron/core/actuator/ProposalApproveActuator.java @@ -41,7 +41,6 @@ public boolean execute(TransactionResultCapsule ret) throws ContractExeException .get(ByteArray.fromLong(proposalApproveContract.getProposalId())) : getDeposit().getProposalCapsule(ByteArray.fromLong(proposalApproveContract .getProposalId())); - ByteString committeeAddress = proposalApproveContract.getOwnerAddress(); if (proposalApproveContract.getIsAddApproval()) { proposalCapsule.addApproval(committeeAddress); diff --git a/src/main/java/org/tron/core/actuator/ProposalCreateActuator.java b/src/main/java/org/tron/core/actuator/ProposalCreateActuator.java index 8e49f1d5c41..676cd851090 100755 --- a/src/main/java/org/tron/core/actuator/ProposalCreateActuator.java +++ b/src/main/java/org/tron/core/actuator/ProposalCreateActuator.java @@ -288,6 +288,38 @@ private void validateValue(Map.Entry entry) throws ContractValidateE } break; } + case (24): { + if (!dbManager.getForkController().pass(ForkBlockVersionEnum.VERSION_3_6)) { + throw new ContractValidateException("Bad chain parameter id"); + } + if (entry.getValue() != 1 && entry.getValue() != 0) { + throw new ContractValidateException( + "This value[ALLOW_PROTO_FILTER_NUM] is only allowed to be 1 or 0"); + } + break; + } + case (25): { + if (!dbManager.getForkController().pass(ForkBlockVersionEnum.VERSION_3_6)) { + throw new ContractValidateException("Bad chain parameter id"); + } + if (entry.getValue() != 1 && entry.getValue() != 0) { + throw new ContractValidateException( + "This value[ALLOW_ACCOUNT_STATE_ROOT] is only allowed to be 1 or 0"); + } + break; + } + case (26): { + if (entry.getValue() != 1) { + throw new ContractValidateException( + "This value[ALLOW_TVM_CONSTANTINOPLE] is only allowed to be 1"); + } + if (dbManager.getDynamicPropertiesStore().getAllowTvmTransferTrc10() == 0) { + throw new ContractValidateException( + "[ALLOW_TVM_TRANSFER_TRC10] proposal must be approved " + + "before [ALLOW_TVM_CONSTANTINOPLE] can be proposed"); + } + break; + } default: break; } diff --git a/src/main/java/org/tron/core/actuator/ProposalDeleteActuator.java b/src/main/java/org/tron/core/actuator/ProposalDeleteActuator.java index 78931a9bc2e..fc9323f3e27 100755 --- a/src/main/java/org/tron/core/actuator/ProposalDeleteActuator.java +++ b/src/main/java/org/tron/core/actuator/ProposalDeleteActuator.java @@ -38,7 +38,6 @@ public boolean execute(TransactionResultCapsule ret) throws ContractExeException ProposalCapsule proposalCapsule = (Objects.isNull(deposit)) ? dbManager.getProposalStore(). get(ByteArray.fromLong(proposalDeleteContract.getProposalId())) : deposit.getProposalCapsule(ByteArray.fromLong(proposalDeleteContract.getProposalId())); - proposalCapsule.setState(State.CANCELED); if (Objects.isNull(deposit)) { dbManager.getProposalStore().put(proposalCapsule.createDbKey(), proposalCapsule); diff --git a/src/main/java/org/tron/core/actuator/UnfreezeBalanceActuator.java b/src/main/java/org/tron/core/actuator/UnfreezeBalanceActuator.java index 1910756a856..b2b9282e822 100755 --- a/src/main/java/org/tron/core/actuator/UnfreezeBalanceActuator.java +++ b/src/main/java/org/tron/core/actuator/UnfreezeBalanceActuator.java @@ -23,6 +23,7 @@ import org.tron.protos.Contract.UnfreezeBalanceContract; import org.tron.protos.Protocol.Account.AccountResource; import org.tron.protos.Protocol.Account.Frozen; +import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Transaction.Result.code; @Slf4j(topic = "actuator") @@ -61,28 +62,40 @@ public boolean execute(TransactionResultCapsule ret) throws ContractExeException DelegatedResourceCapsule delegatedResourceCapsule = dbManager.getDelegatedResourceStore() .get(key); - AccountCapsule receiverCapsule = dbManager.getAccountStore().get(receiverAddress); - switch (unfreezeBalanceContract.getResource()) { case BANDWIDTH: unfreezeBalance = delegatedResourceCapsule.getFrozenBalanceForBandwidth(); delegatedResourceCapsule.setFrozenBalanceForBandwidth(0, 0); - receiverCapsule.addAcquiredDelegatedFrozenBalanceForBandwidth(-unfreezeBalance); accountCapsule.addDelegatedFrozenBalanceForBandwidth(-unfreezeBalance); break; case ENERGY: unfreezeBalance = delegatedResourceCapsule.getFrozenBalanceForEnergy(); delegatedResourceCapsule.setFrozenBalanceForEnergy(0, 0); - receiverCapsule.addAcquiredDelegatedFrozenBalanceForEnergy(-unfreezeBalance); accountCapsule.addDelegatedFrozenBalanceForEnergy(-unfreezeBalance); break; default: //this should never happen break; } - accountCapsule.setBalance(oldBalance + unfreezeBalance); - dbManager.getAccountStore().put(receiverCapsule.createDbKey(), receiverCapsule); + AccountCapsule receiverCapsule = dbManager.getAccountStore().get(receiverAddress); + if (dbManager.getDynamicPropertiesStore().getAllowTvmConstantinople() == 0 || + (receiverCapsule != null && receiverCapsule.getType() != AccountType.Contract)) { + switch (unfreezeBalanceContract.getResource()) { + case BANDWIDTH: + receiverCapsule.addAcquiredDelegatedFrozenBalanceForBandwidth(-unfreezeBalance); + break; + case ENERGY: + receiverCapsule.addAcquiredDelegatedFrozenBalanceForEnergy(-unfreezeBalance); + break; + default: + //this should never happen + break; + } + dbManager.getAccountStore().put(receiverCapsule.createDbKey(), receiverCapsule); + } + + accountCapsule.setBalance(oldBalance + unfreezeBalance); if (delegatedResourceCapsule.getFrozenBalanceForBandwidth() == 0 && delegatedResourceCapsule.getFrozenBalanceForEnergy() == 0) { @@ -239,10 +252,11 @@ public boolean validate() throws ContractValidateException { } AccountCapsule receiverCapsule = dbManager.getAccountStore().get(receiverAddress); - if (receiverCapsule == null) { - String readableOwnerAddress = StringUtil.createReadableString(receiverAddress); + if (dbManager.getDynamicPropertiesStore().getAllowTvmConstantinople() == 0 + && receiverCapsule == null) { + String readableReceiverAddress = StringUtil.createReadableString(receiverAddress); throw new ContractValidateException( - "Account[" + readableOwnerAddress + "] not exists"); + "Receiver Account[" + readableReceiverAddress + "] not exists"); } byte[] key = DelegatedResourceCapsule @@ -260,14 +274,28 @@ public boolean validate() throws ContractValidateException { if (delegatedResourceCapsule.getFrozenBalanceForBandwidth() <= 0) { throw new ContractValidateException("no delegatedFrozenBalance(BANDWIDTH)"); } - if (receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() - < delegatedResourceCapsule.getFrozenBalanceForBandwidth()) { - throw new ContractValidateException( - "AcquiredDelegatedFrozenBalanceForBandwidth[" + receiverCapsule - .getAcquiredDelegatedFrozenBalanceForBandwidth() + "] < delegatedBandwidth[" - + delegatedResourceCapsule.getFrozenBalanceForBandwidth() - + "],this should never happen"); + + if (dbManager.getDynamicPropertiesStore().getAllowTvmConstantinople() == 0) { + if (receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() + < delegatedResourceCapsule.getFrozenBalanceForBandwidth()) { + throw new ContractValidateException( + "AcquiredDelegatedFrozenBalanceForBandwidth[" + receiverCapsule + .getAcquiredDelegatedFrozenBalanceForBandwidth() + "] < delegatedBandwidth[" + + delegatedResourceCapsule.getFrozenBalanceForBandwidth() + + "]"); + } + } else { + if (receiverCapsule != null && receiverCapsule.getType() != AccountType.Contract + && receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() + < delegatedResourceCapsule.getFrozenBalanceForBandwidth()) { + throw new ContractValidateException( + "AcquiredDelegatedFrozenBalanceForBandwidth[" + receiverCapsule + .getAcquiredDelegatedFrozenBalanceForBandwidth() + "] < delegatedBandwidth[" + + delegatedResourceCapsule.getFrozenBalanceForBandwidth() + + "]"); + } } + if (delegatedResourceCapsule.getExpireTimeForBandwidth() > now) { throw new ContractValidateException("It's not time to unfreeze."); } @@ -276,14 +304,27 @@ public boolean validate() throws ContractValidateException { if (delegatedResourceCapsule.getFrozenBalanceForEnergy() <= 0) { throw new ContractValidateException("no delegateFrozenBalance(Energy)"); } - if (receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy() - < delegatedResourceCapsule.getFrozenBalanceForEnergy()) { - throw new ContractValidateException( - "AcquiredDelegatedFrozenBalanceForEnergy[" + receiverCapsule - .getAcquiredDelegatedFrozenBalanceForEnergy() + "] < delegatedEnergy[" - + delegatedResourceCapsule.getFrozenBalanceForEnergy() + - "],this should never happen"); + if (dbManager.getDynamicPropertiesStore().getAllowTvmConstantinople() == 0) { + if (receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy() + < delegatedResourceCapsule.getFrozenBalanceForEnergy()) { + throw new ContractValidateException( + "AcquiredDelegatedFrozenBalanceForEnergy[" + receiverCapsule + .getAcquiredDelegatedFrozenBalanceForEnergy() + "] < delegatedEnergy[" + + delegatedResourceCapsule.getFrozenBalanceForEnergy() + + "]"); + } + } else { + if (receiverCapsule != null && receiverCapsule.getType() != AccountType.Contract + && receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy() + < delegatedResourceCapsule.getFrozenBalanceForEnergy()) { + throw new ContractValidateException( + "AcquiredDelegatedFrozenBalanceForEnergy[" + receiverCapsule + .getAcquiredDelegatedFrozenBalanceForEnergy() + "] < delegatedEnergy[" + + delegatedResourceCapsule.getFrozenBalanceForEnergy() + + "]"); + } } + if (delegatedResourceCapsule.getExpireTimeForEnergy(dbManager) > now) { throw new ContractValidateException("It's not time to unfreeze."); } diff --git a/src/main/java/org/tron/core/capsule/AccountCapsule.java b/src/main/java/org/tron/core/capsule/AccountCapsule.java index f2b16414015..e15eb3fabe1 100644 --- a/src/main/java/org/tron/core/capsule/AccountCapsule.java +++ b/src/main/java/org/tron/core/capsule/AccountCapsule.java @@ -28,6 +28,7 @@ import org.tron.protos.Contract.AccountUpdateContract; import org.tron.protos.Protocol.Account; import org.tron.protos.Protocol.Account.AccountResource; +import org.tron.protos.Protocol.Account.Builder; import org.tron.protos.Protocol.Account.Frozen; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Key; @@ -986,4 +987,18 @@ public void updatePermissions(Permission owner, Permission witness, List { @@ -68,14 +69,13 @@ public static TriggerSmartContract getTriggerContractFromTransaction(Transaction } } - public Sha256Hash getHash() { - byte[] transBytes = this.smartContract.toByteArray(); - return Sha256Hash.of(transBytes); + public byte[] getCodeHash() { + return this.smartContract.getCodeHash().toByteArray(); } - public Sha256Hash getCodeHash() { - byte[] bytecode = smartContract.getBytecode().toByteArray(); - return Sha256Hash.of(bytecode); + public void setCodeHash(byte[] codeHash) { + this.smartContract = this.smartContract.toBuilder().setCodeHash(ByteString.copyFrom(codeHash)) + .build(); } @Override @@ -109,4 +109,12 @@ public long getOriginEnergyLimit() { } return originEnergyLimit; } + + public void clearABI() { + this.smartContract = this.smartContract.toBuilder().setAbi(ABI.getDefaultInstance()).build(); + } + + public byte[] getTrxHash() { + return this.smartContract.getTrxHash().toByteArray(); + } } diff --git a/src/main/java/org/tron/core/capsule/ReceiptCapsule.java b/src/main/java/org/tron/core/capsule/ReceiptCapsule.java index 166eb99dc23..3976fc9bd12 100644 --- a/src/main/java/org/tron/core/capsule/ReceiptCapsule.java +++ b/src/main/java/org/tron/core/capsule/ReceiptCapsule.java @@ -1,5 +1,6 @@ package org.tron.core.capsule; +import java.util.Objects; import lombok.Getter; import lombok.Setter; import org.tron.common.runtime.config.VMConfig; @@ -105,6 +106,11 @@ public void payEnergyBill(Manager manager, AccountCapsule origin, AccountCapsule return; } + if (Objects.isNull(origin) && VMConfig.allowTvmConstantinople()) { + payEnergyBill(manager, caller, receipt.getEnergyUsageTotal(), energyProcessor, now); + return; + } + if (caller.getAddress().equals(origin.getAddress())) { payEnergyBill(manager, caller, receipt.getEnergyUsageTotal(), energyProcessor, now); } else { diff --git a/src/main/java/org/tron/core/capsule/StorageRowCapsule.java b/src/main/java/org/tron/core/capsule/StorageRowCapsule.java index c384672cfeb..2ab63c17633 100644 --- a/src/main/java/org/tron/core/capsule/StorageRowCapsule.java +++ b/src/main/java/org/tron/core/capsule/StorageRowCapsule.java @@ -19,7 +19,6 @@ import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; -import org.spongycastle.util.encoders.Hex; import org.tron.common.runtime.vm.DataWord; import org.tron.common.utils.Sha256Hash; diff --git a/src/main/java/org/tron/core/capsule/TransactionCapsule.java b/src/main/java/org/tron/core/capsule/TransactionCapsule.java index a9e32de57b0..a8d2defa6d1 100755 --- a/src/main/java/org/tron/core/capsule/TransactionCapsule.java +++ b/src/main/java/org/tron/core/capsule/TransactionCapsule.java @@ -15,6 +15,7 @@ package org.tron.core.capsule; +import static org.tron.core.exception.P2pException.TypeEnum.PROTOBUF_ERROR; import static org.tron.protos.Contract.AssetIssueContract; import static org.tron.protos.Contract.VoteAssetContract; import static org.tron.protos.Contract.VoteWitnessContract; @@ -23,37 +24,33 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; +import com.google.protobuf.CodedInputStream; +import com.google.protobuf.Internal; import com.google.protobuf.InvalidProtocolBufferException; +import java.io.IOException; import java.security.SignatureException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import java.util.Objects; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicInteger; import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; -import org.springframework.util.StringUtils; import org.tron.common.crypto.ECKey; import org.tron.common.crypto.ECKey.ECDSASignature; -import org.tron.common.runtime.Runtime; -import org.tron.common.runtime.vm.program.Program.BadJumpDestinationException; -import org.tron.common.runtime.vm.program.Program.BytecodeExecutionException; -import org.tron.common.runtime.vm.program.Program.IllegalOperationException; -import org.tron.common.runtime.vm.program.Program.JVMStackOverFlowException; -import org.tron.common.runtime.vm.program.Program.OutOfEnergyException; -import org.tron.common.runtime.vm.program.Program.OutOfMemoryException; -import org.tron.common.runtime.vm.program.Program.OutOfTimeException; -import org.tron.common.runtime.vm.program.Program.PrecompiledContractException; -import org.tron.common.runtime.vm.program.Program.StackTooLargeException; -import org.tron.common.runtime.vm.program.Program.StackTooSmallException; +import org.tron.common.overlay.message.Message; import org.tron.common.utils.ByteArray; import org.tron.common.utils.Sha256Hash; import org.tron.core.Wallet; +import org.tron.core.config.args.Args; import org.tron.core.db.AccountStore; import org.tron.core.db.Manager; import org.tron.core.db.TransactionTrace; import org.tron.core.exception.BadItemException; +import org.tron.core.exception.P2pException; import org.tron.core.exception.PermissionException; import org.tron.core.exception.SignatureFormatException; import org.tron.core.exception.ValidateSignatureException; @@ -61,6 +58,7 @@ import org.tron.protos.Contract.AccountCreateContract; import org.tron.protos.Contract.AccountPermissionUpdateContract; import org.tron.protos.Contract.AccountUpdateContract; +import org.tron.protos.Contract.ClearABIContract; import org.tron.protos.Contract.CreateSmartContract; import org.tron.protos.Contract.ExchangeCreateContract; import org.tron.protos.Contract.ExchangeInjectContract; @@ -105,6 +103,9 @@ public class TransactionCapsule implements ProtoCapsule { @Setter private TransactionTrace trxTrace; + private static final ExecutorService executorService = Executors + .newFixedThreadPool(Args.getInstance().getValidContractProtoThreadNum()); + /** * constructor TransactionCapsule. */ @@ -117,8 +118,16 @@ public TransactionCapsule(Transaction trx) { */ public TransactionCapsule(byte[] data) throws BadItemException { try { - this.transaction = Transaction.parseFrom(data); - } catch (InvalidProtocolBufferException e) { + this.transaction = Transaction.parseFrom(Message.getCodedInputStream(data)); + } catch (Exception e) { + throw new BadItemException("Transaction proto data parse exception"); + } + } + + public TransactionCapsule(CodedInputStream codedInputStream) throws BadItemException { + try { + this.transaction = Transaction.parseFrom(codedInputStream); + } catch (IOException e) { throw new BadItemException("Transaction proto data parse exception"); } } @@ -279,9 +288,9 @@ public static long checkWeight(Permission permission, List sigs, byt List approveList) throws SignatureException, PermissionException, SignatureFormatException { long currentWeight = 0; -// if (signature.size() % 65 != 0) { -// throw new SignatureFormatException("Signature size is " + signature.size()); -// } + // if (signature.size() % 65 != 0) { + // throw new SignatureFormatException("Signature size is " + signature.size()); + // } if (sigs.size() > permission.getKeysCount()) { throw new PermissionException( "Signature count is " + (sigs.size()) + " more than key counts of permission : " @@ -426,15 +435,15 @@ public static byte[] getOwner(Transaction.Contract contract) { case SetAccountIdContract: owner = contractParameter.unpack(SetAccountIdContract.class).getOwnerAddress(); break; -// case BuyStorageContract: -// owner = contractParameter.unpack(BuyStorageContract.class).getOwnerAddress(); -// break; -// case BuyStorageBytesContract: -// owner = contractParameter.unpack(BuyStorageBytesContract.class).getOwnerAddress(); -// break; -// case SellStorageContract: -// owner = contractParameter.unpack(SellStorageContract.class).getOwnerAddress(); -// break; + //case BuyStorageContract: + // owner = contractParameter.unpack(BuyStorageContract.class).getOwnerAddress(); + // break; + //case BuyStorageBytesContract: + // owner = contractParameter.unpack(BuyStorageBytesContract.class).getOwnerAddress(); + // break; + //case SellStorageContract: + // owner = contractParameter.unpack(SellStorageContract.class).getOwnerAddress(); + // break; case UpdateSettingContract: owner = contractParameter.unpack(UpdateSettingContract.class) .getOwnerAddress(); @@ -443,6 +452,10 @@ public static byte[] getOwner(Transaction.Contract contract) { owner = contractParameter.unpack(UpdateEnergyLimitContract.class) .getOwnerAddress(); break; + case ClearABIContract: + owner = contractParameter.unpack(ClearABIContract.class) + .getOwnerAddress(); + break; case ExchangeCreateContract: owner = contractParameter.unpack(ExchangeCreateContract.class).getOwnerAddress(); break; @@ -469,6 +482,147 @@ public static byte[] getOwner(Transaction.Contract contract) { } } + public static T parse(Class clazz, + CodedInputStream codedInputStream) throws InvalidProtocolBufferException { + T defaultInstance = Internal.getDefaultInstance(clazz); + return (T) defaultInstance.getParserForType().parseFrom(codedInputStream); + } + + public static void validContractProto(List transactionList) throws P2pException { + List> futureList = new ArrayList<>(); + transactionList.forEach(transaction -> { + Future future = executorService.submit(() -> { + try { + validContractProto(transaction.getRawData().getContract(0)); + return true; + } catch (Exception e) { + logger.error("{}", e.getMessage()); + } + return false; + }); + futureList.add(future); + }); + for (Future future : futureList) { + try { + if (!future.get()) { + throw new P2pException(PROTOBUF_ERROR, PROTOBUF_ERROR.getDesc()); + } + } catch (Exception e) { + throw new P2pException(PROTOBUF_ERROR, PROTOBUF_ERROR.getDesc()); + } + } + } + + public static void validContractProto(Transaction.Contract contract) + throws InvalidProtocolBufferException, P2pException { + Any contractParameter = contract.getParameter(); + Class clazz = null; + switch (contract.getType()) { + case AccountCreateContract: + clazz = AccountCreateContract.class; + break; + case TransferContract: + clazz = TransferContract.class; + break; + case TransferAssetContract: + clazz = TransferAssetContract.class; + break; + case VoteAssetContract: + clazz = VoteAssetContract.class; + break; + case VoteWitnessContract: + clazz = VoteWitnessContract.class; + break; + case WitnessCreateContract: + clazz = WitnessCreateContract.class; + break; + case AssetIssueContract: + clazz = AssetIssueContract.class; + break; + case WitnessUpdateContract: + clazz = WitnessUpdateContract.class; + break; + case ParticipateAssetIssueContract: + clazz = ParticipateAssetIssueContract.class; + break; + case AccountUpdateContract: + clazz = AccountUpdateContract.class; + break; + case FreezeBalanceContract: + clazz = FreezeBalanceContract.class; + break; + case UnfreezeBalanceContract: + clazz = UnfreezeBalanceContract.class; + break; + case UnfreezeAssetContract: + clazz = UnfreezeAssetContract.class; + break; + case WithdrawBalanceContract: + clazz = WithdrawBalanceContract.class; + break; + case CreateSmartContract: + clazz = Contract.CreateSmartContract.class; + break; + case TriggerSmartContract: + clazz = Contract.TriggerSmartContract.class; + break; + case UpdateAssetContract: + clazz = UpdateAssetContract.class; + break; + case ProposalCreateContract: + clazz = ProposalCreateContract.class; + break; + case ProposalApproveContract: + clazz = ProposalApproveContract.class; + break; + case ProposalDeleteContract: + clazz = ProposalDeleteContract.class; + break; + case SetAccountIdContract: + clazz = SetAccountIdContract.class; + break; + case UpdateSettingContract: + clazz = UpdateSettingContract.class; + break; + case UpdateEnergyLimitContract: + clazz = UpdateEnergyLimitContract.class; + break; + case ClearABIContract: + clazz = ClearABIContract.class; + break; + case ExchangeCreateContract: + clazz = ExchangeCreateContract.class; + break; + case ExchangeInjectContract: + clazz = ExchangeInjectContract.class; + break; + case ExchangeWithdrawContract: + clazz = ExchangeWithdrawContract.class; + break; + case ExchangeTransactionContract: + clazz = ExchangeTransactionContract.class; + break; + case AccountPermissionUpdateContract: + clazz = AccountPermissionUpdateContract.class; + break; + // todo add other contract + default: + break; + } + if (clazz == null) { + throw new P2pException(PROTOBUF_ERROR, PROTOBUF_ERROR.getDesc()); + } + com.google.protobuf.Message src = contractParameter.unpack(clazz); + com.google.protobuf.Message contractMessage = parse(clazz, + Message.getCodedInputStream(src.toByteArray())); + + // if (!src.equals(contractMessage)) { + // throw new P2pException(PROTOBUF_ERROR, PROTOBUF_ERROR.getDesc()); + // } + + Message.compareBytes(src.toByteArray(), contractMessage.toByteArray()); + } + // todo mv this static function to capsule util public static byte[] getToAddress(Transaction.Contract contract) { ByteString to; @@ -601,8 +755,8 @@ public boolean validateSignature(Manager manager) || this.transaction.getRawData().getContractCount() <= 0) { throw new ValidateSignatureException("miss sig or contract"); } - if (this.transaction.getSignatureCount() > - manager.getDynamicPropertiesStore().getTotalSignNum()) { + if (this.transaction.getSignatureCount() > manager.getDynamicPropertiesStore() + .getTotalSignNum()) { throw new ValidateSignatureException("too many signatures"); } byte[] hash = this.getRawHash().getBytes(); @@ -706,57 +860,6 @@ public String toString() { return toStringBuff.toString(); } - public void setResult(Runtime runtime) { - RuntimeException exception = runtime.getResult().getException(); - if (Objects.isNull(exception) && StringUtils - .isEmpty(runtime.getRuntimeError()) && !runtime.getResult().isRevert()) { - this.setResultCode(contractResult.SUCCESS); - return; - } - if (runtime.getResult().isRevert()) { - this.setResultCode(contractResult.REVERT); - return; - } - if (exception instanceof IllegalOperationException) { - this.setResultCode(contractResult.ILLEGAL_OPERATION); - return; - } - if (exception instanceof OutOfEnergyException) { - this.setResultCode(contractResult.OUT_OF_ENERGY); - return; - } - if (exception instanceof BadJumpDestinationException) { - this.setResultCode(contractResult.BAD_JUMP_DESTINATION); - return; - } - if (exception instanceof OutOfTimeException) { - this.setResultCode(contractResult.OUT_OF_TIME); - return; - } - if (exception instanceof OutOfMemoryException) { - this.setResultCode(contractResult.OUT_OF_MEMORY); - return; - } - if (exception instanceof PrecompiledContractException) { - this.setResultCode(contractResult.PRECOMPILED_CONTRACT); - return; - } - if (exception instanceof StackTooSmallException) { - this.setResultCode(contractResult.STACK_TOO_SMALL); - return; - } - if (exception instanceof StackTooLargeException) { - this.setResultCode(contractResult.STACK_TOO_LARGE); - return; - } - if (exception instanceof JVMStackOverFlowException) { - this.setResultCode(contractResult.JVM_STACK_OVER_FLOW); - return; - } - this.setResultCode(contractResult.UNKNOWN); - return; - } - public void setResultCode(contractResult code) { Result ret = Result.newBuilder().setContractRet(code).build(); if (this.transaction.getRetCount() > 0) { diff --git a/src/main/java/org/tron/core/capsule/utils/BlockUtil.java b/src/main/java/org/tron/core/capsule/utils/BlockUtil.java index 53eb013ce05..bbb640558dd 100644 --- a/src/main/java/org/tron/core/capsule/utils/BlockUtil.java +++ b/src/main/java/org/tron/core/capsule/utils/BlockUtil.java @@ -17,11 +17,15 @@ import com.google.protobuf.ByteString; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; import org.tron.common.utils.ByteArray; +import org.tron.common.utils.Sha256Hash; import org.tron.core.capsule.BlockCapsule; import org.tron.core.config.args.Args; import org.tron.core.config.args.GenesisBlock; +import org.tron.core.db.Manager; +import org.tron.core.witness.WitnessController; import org.tron.protos.Protocol.Transaction; public class BlockUtil { @@ -64,4 +68,17 @@ public static BlockCapsule newGenesisBlockCapsule() { public static boolean isParentOf(BlockCapsule blockCapsule1, BlockCapsule blockCapsule2) { return blockCapsule1.getBlockId().equals(blockCapsule2.getParentHash()); } + + public static BlockCapsule createTestBlockCapsule(Manager dbManager, long time, + long number, ByteString hash, Map addressToProvateKeys) { + WitnessController witnessController = dbManager.getWitnessController(); + ByteString witnessAddress = + witnessController.getScheduledWitness(witnessController.getSlotAtTime(time)); + BlockCapsule blockCapsule = new BlockCapsule(number, Sha256Hash.wrap(hash), time, + witnessAddress); + blockCapsule.generatedByMyself = true; + blockCapsule.setMerkleRoot(); + blockCapsule.sign(ByteArray.fromHexString(addressToProvateKeys.get(witnessAddress))); + return blockCapsule; + } } diff --git a/src/main/java/org/tron/core/capsule/utils/ByteArrayWrapper.java b/src/main/java/org/tron/core/capsule/utils/ByteArrayWrapper.java new file mode 100644 index 00000000000..43808f6ec85 --- /dev/null +++ b/src/main/java/org/tron/core/capsule/utils/ByteArrayWrapper.java @@ -0,0 +1,54 @@ + +package org.tron.core.capsule.utils; + +import static org.tron.common.utils.ByteUtil.toHexString; + +import java.io.Serializable; +import java.util.Arrays; + +/** + */ +public class ByteArrayWrapper implements Comparable, Serializable { + + private final byte[] data; + private int hashCode = 0; + + public ByteArrayWrapper(byte[] data) { + if (data == null) { + throw new NullPointerException("Data must not be null"); + } + this.data = data; + this.hashCode = Arrays.hashCode(data); + } + + public boolean equals(Object other) { + if (!(other instanceof ByteArrayWrapper)) { + return false; + } + byte[] otherData = ((ByteArrayWrapper) other).getData(); + return FastByteComparisons.compareTo( + data, 0, data.length, + otherData, 0, otherData.length) == 0; + } + + @Override + public int hashCode() { + return hashCode; + } + + @Override + public int compareTo(ByteArrayWrapper o) { + return FastByteComparisons.compareTo( + data, 0, data.length, + o.getData(), 0, o.getData().length); + } + + public byte[] getData() { + return data; + } + + @Override + public String toString() { + return toHexString(data); + } +} diff --git a/src/main/java/org/tron/core/capsule/utils/DecodeResult.java b/src/main/java/org/tron/core/capsule/utils/DecodeResult.java new file mode 100644 index 00000000000..89816b12193 --- /dev/null +++ b/src/main/java/org/tron/core/capsule/utils/DecodeResult.java @@ -0,0 +1,44 @@ + +package org.tron.core.capsule.utils; + +import java.io.Serializable; +import org.spongycastle.util.encoders.Hex; + +@SuppressWarnings("serial") +public class DecodeResult implements Serializable { + + private int pos; + private Object decoded; + + public DecodeResult(int pos, Object decoded) { + this.pos = pos; + this.decoded = decoded; + } + + public int getPos() { + return pos; + } + + public Object getDecoded() { + return decoded; + } + + public String toString() { + return asString(this.decoded); + } + + private String asString(Object decoded) { + if (decoded instanceof String) { + return (String) decoded; + } else if (decoded instanceof byte[]) { + return Hex.toHexString((byte[]) decoded); + } else if (decoded instanceof Object[]) { + String result = ""; + for (Object item : (Object[]) decoded) { + result += asString(item); + } + return result; + } + throw new RuntimeException("Not a valid type. Should not occur"); + } +} diff --git a/src/main/java/org/tron/core/capsule/utils/ExchangeProcessor.java b/src/main/java/org/tron/core/capsule/utils/ExchangeProcessor.java index 4b76e17c971..b12ce4ac3d9 100644 --- a/src/main/java/org/tron/core/capsule/utils/ExchangeProcessor.java +++ b/src/main/java/org/tron/core/capsule/utils/ExchangeProcessor.java @@ -11,7 +11,7 @@ public ExchangeProcessor(long supply) { this.supply = supply; } - private long exchange_to_supply(long balance, long quant) { + private long exchangeToSupply(long balance, long quant) { logger.debug("balance: " + balance); long newBalance = balance + quant; logger.debug("balance + quant: " + newBalance); @@ -24,39 +24,19 @@ private long exchange_to_supply(long balance, long quant) { return out; } - private long exchange_to_supply2(long balance, long quant) { - logger.debug("balance: " + balance); - long newBalance = balance - quant; - logger.debug("balance - quant: " + (balance - quant)); - - double issuedSupply = -supply * (1.0 - Math.pow(1.0 + (double) quant / newBalance, 0.0005)); - logger.debug("issuedSupply: " + issuedSupply); - long out = (long) issuedSupply; - supply += out; - - return out; - } - - private long exchange_from_supply(long balance, long supplyQuant) { + private long exchangeFromSupply(long balance, long supplyQuant) { supply -= supplyQuant; double exchangeBalance = balance * (Math.pow(1.0 + (double) supplyQuant / supply, 2000.0) - 1.0); logger.debug("exchangeBalance: " + exchangeBalance); - long out = (long) exchangeBalance; - long newBalance = balance - out; - -// if (isTRX) { -// out = Math.round(exchangeBalance / 100000) * 100000; -// logger.info("---out: " + out); -// } - return out; + return (long) exchangeBalance; } public long exchange(long sellTokenBalance, long buyTokenBalance, long sellTokenQuant) { - long relay = exchange_to_supply(sellTokenBalance, sellTokenQuant); - return exchange_from_supply(buyTokenBalance, relay); + long relay = exchangeToSupply(sellTokenBalance, sellTokenQuant); + return exchangeFromSupply(buyTokenBalance, relay); } } diff --git a/src/main/java/org/tron/core/capsule/utils/FastByteComparisons.java b/src/main/java/org/tron/core/capsule/utils/FastByteComparisons.java new file mode 100644 index 00000000000..20fcbc9800a --- /dev/null +++ b/src/main/java/org/tron/core/capsule/utils/FastByteComparisons.java @@ -0,0 +1,100 @@ + +package org.tron.core.capsule.utils; + +import com.google.common.primitives.UnsignedBytes; + + +/** + * Utility code to do optimized byte-array comparison. + * This is borrowed and slightly modified from Guava's {@link UnsignedBytes} + * class to be able to compare arrays that start at non-zero offsets. + */ +@SuppressWarnings("restriction") +public abstract class FastByteComparisons { + + public static boolean equalByte(byte[] b1, byte[] b2) { + return b1.length == b2.length && compareTo(b1, 0, b1.length, b2, 0, b2.length) == 0; + } + /** + * Lexicographically compare two byte arrays. + * + * @param b1 buffer1 + * @param s1 offset1 + * @param l1 length1 + * @param b2 buffer2 + * @param s2 offset2 + * @param l2 length2 + * @return int + */ + public static int compareTo(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) { + return LexicographicalComparerHolder.BEST_COMPARER.compareTo( + b1, s1, l1, b2, s2, l2); + } + + private interface Comparer { + int compareTo(T buffer1, int offset1, int length1, + T buffer2, int offset2, int length2); + } + + private static Comparer lexicographicalComparerJavaImpl() { + return LexicographicalComparerHolder.PureJavaComparer.INSTANCE; + } + + + /** + * + *

Uses reflection to gracefully fall back to the Java implementation if + * {@code Unsafe} isn't available. + */ + private static class LexicographicalComparerHolder { + static final String UNSAFE_COMPARER_NAME = + LexicographicalComparerHolder.class.getName() + "$UnsafeComparer"; + + static final Comparer BEST_COMPARER = getBestComparer(); + + /** + * Returns the Unsafe-using Comparer, or falls back to the pure-Java + * implementation if unable to do so. + */ + static Comparer getBestComparer() { + try { + Class theClass = Class.forName(UNSAFE_COMPARER_NAME); + + // yes, UnsafeComparer does implement Comparer + @SuppressWarnings("unchecked") + Comparer comparer = + (Comparer) theClass.getEnumConstants()[0]; + return comparer; + } catch (Throwable t) { // ensure we really catch *everything* + return lexicographicalComparerJavaImpl(); + } + } + + private enum PureJavaComparer implements Comparer { + INSTANCE; + + @Override + public int compareTo(byte[] buffer1, int offset1, int length1, + byte[] buffer2, int offset2, int length2) { + // Short circuit equal case + if (buffer1 == buffer2 && + offset1 == offset2 && + length1 == length2) { + return 0; + } + int end1 = offset1 + length1; + int end2 = offset2 + length2; + for (int i = offset1, j = offset2; i < end1 && j < end2; i++, j++) { + int a = (buffer1[i] & 0xff); + int b = (buffer2[j] & 0xff); + if (a != b) { + return a - b; + } + } + return length1 - length2; + } + } + + + } +} diff --git a/src/main/java/org/tron/core/capsule/utils/RLP.java b/src/main/java/org/tron/core/capsule/utils/RLP.java new file mode 100644 index 00000000000..91568015328 --- /dev/null +++ b/src/main/java/org/tron/core/capsule/utils/RLP.java @@ -0,0 +1,1286 @@ + +package org.tron.core.capsule.utils; + +import static java.util.Arrays.copyOfRange; +import static org.spongycastle.util.Arrays.concatenate; +import static org.spongycastle.util.BigIntegers.asUnsignedByteArray; +import static org.tron.common.utils.ByteUtil.byteArrayToInt; +import static org.tron.common.utils.ByteUtil.intToBytesNoLeadZeroes; +import static org.tron.common.utils.ByteUtil.isNullOrZeroArray; +import static org.tron.common.utils.ByteUtil.isSingleZero; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.spongycastle.util.encoders.Hex; +import org.tron.common.utils.ByteUtil; +import org.tron.common.utils.Value; + +/** + * Recursive Length Prefix (RLP) encoding. + *

+ * The purpose of RLP is to encode arbitrarily nested arrays of binary data, and RLP is the main + * encoding method used to serialize objects in Ethereum. The only purpose of RLP is to encode + * structure; encoding specific atomic data types (eg. strings, integers, floats) is left up to + * higher-order protocols; in Ethereum the standard is that integers are represented in big endian + * binary form. If one wishes to use RLP to encode a dictionary, the two suggested canonical forms + * are to either use [[k1,v1],[k2,v2]...] with keys in lexicographic order or to use the + * higher-level Patricia Tree encoding as Ethereum does. + *

+ * The RLP encoding function takes in an item. An item is defined as follows: + *

+ * - A string (ie. byte array) is an item - A list of items is an item + *

+ * For example, an empty string is an item, as is the string containing the word "cat", a list + * containing any number of strings, as well as more complex data structures like + * ["cat",["puppy","cow"],"horse",[[]],"pig",[""],"sheep"]. Note that in the context of the rest of + * this article, "string" will be used as a synonym for "a certain number of bytes of binary data"; + * no special encodings are used and no knowledge about the content of the strings is implied. + *

+ * See: https://github.com/ethereum/wiki/wiki/%5BEnglish%5D-RLP + * + * @author Roman Mandeleil + * @since 01.04.2014 + */ +public class RLP { + + private static final Logger logger = LoggerFactory.getLogger("rlp"); + + + public static final byte[] EMPTY_ELEMENT_RLP = encodeElement(new byte[0]); + + private static final int MAX_DEPTH = 16; + + /** + * Allow for content up to size of 2^64 bytes * + */ + private static final double MAX_ITEM_LENGTH = Math.pow(256, 8); + + /** + * Reason for threshold according to Vitalik Buterin: - 56 bytes maximizes the benefit of both + * options - if we went with 60 then we would have only had 4 slots for long strings so RLP would + * not have been able to store objects above 4gb - if we went with 48 then RLP would be fine for + * 2^128 space, but that's way too much - so 56 and 2^64 space seems like the right place to put + * the cutoff - also, that's where Bitcoin's varint does the cutof + */ + private static final int SIZE_THRESHOLD = 56; + + /** RLP encoding rules are defined as follows: */ + + /* + * For a single byte whose value is in the [0x00, 0x7f] range, that byte is + * its own RLP encoding. + */ + + /** + * [0x80] If a string is 0-55 bytes long, the RLP encoding consists of a single byte with value + * 0x80 plus the length of the string followed by the string. The range of the first byte is thus + * [0x80, 0xb7]. + */ + private static final int OFFSET_SHORT_ITEM = 0x80; + + /** + * [0xb7] If a string is more than 55 bytes long, the RLP encoding consists of a single byte with + * value 0xb7 plus the length of the length of the string in binary form, followed by the length + * of the string, followed by the string. For example, a length-1024 string would be encoded as + * \xb9\x04\x00 followed by the string. The range of the first byte is thus [0xb8, 0xbf]. + */ + private static final int OFFSET_LONG_ITEM = 0xb7; + + /** + * [0xc0] If the total payload of a list (i.e. the combined length of all its items) is 0-55 bytes + * long, the RLP encoding consists of a single byte with value 0xc0 plus the length of the list + * followed by the concatenation of the RLP encodings of the items. The range of the first byte is + * thus [0xc0, 0xf7]. + */ + private static final int OFFSET_SHORT_LIST = 0xc0; + + /** + * [0xf7] If the total payload of a list is more than 55 bytes long, the RLP encoding consists of + * a single byte with value 0xf7 plus the length of the length of the list in binary form, + * followed by the length of the list, followed by the concatenation of the RLP encodings of the + * items. The range of the first byte is thus [0xf8, 0xff]. + */ + private static final int OFFSET_LONG_LIST = 0xf7; + + + /* ****************************************************** + * DECODING * + * ******************************************************/ + + private static byte decodeOneByteItem(byte[] data, int index) { + // null item + if ((data[index] & 0xFF) == OFFSET_SHORT_ITEM) { + return (byte) (data[index] - OFFSET_SHORT_ITEM); + } + // single byte item + if ((data[index] & 0xFF) < OFFSET_SHORT_ITEM) { + return data[index]; + } + // single byte item + if ((data[index] & 0xFF) == OFFSET_SHORT_ITEM + 1) { + return data[index + 1]; + } + return 0; + } + + public static int decodeInt(byte[] data, int index) { + + int value = 0; + // NOTE: From RLP doc: + // Ethereum integers must be represented in big endian binary form + // with no leading zeroes (thus making the integer value zero be + // equivalent to the empty byte array) + + if (data[index] == 0x00) { + throw new RuntimeException("not a number"); + } else if ((data[index] & 0xFF) < OFFSET_SHORT_ITEM) { + + return data[index]; + + } else if ((data[index] & 0xFF) <= OFFSET_SHORT_ITEM + Integer.BYTES) { + + byte length = (byte) (data[index] - OFFSET_SHORT_ITEM); + byte pow = (byte) (length - 1); + for (int i = 1; i <= length; ++i) { + // << (8 * pow) == bit shift to 0 (*1), 8 (*256) , 16 (*65..).. + value += (data[index + i] & 0xFF) << (8 * pow); + pow--; + } + } else { + + // If there are more than 4 bytes, it is not going + // to decode properly into an int. + throw new RuntimeException("wrong decode attempt"); + } + return value; + } + + static short decodeShort(byte[] data, int index) { + + short value = 0; + + if (data[index] == 0x00) { + throw new RuntimeException("not a number"); + } else if ((data[index] & 0xFF) < OFFSET_SHORT_ITEM) { + + return data[index]; + + } else if ((data[index] & 0xFF) <= OFFSET_SHORT_ITEM + Short.BYTES) { + + byte length = (byte) (data[index] - OFFSET_SHORT_ITEM); + byte pow = (byte) (length - 1); + for (int i = 1; i <= length; ++i) { + // << (8 * pow) == bit shift to 0 (*1), 8 (*256) , 16 (*65..) + value += (data[index + i] & 0xFF) << (8 * pow); + pow--; + } + } else { + + // If there are more than 2 bytes, it is not going + // to decode properly into a short. + throw new RuntimeException("wrong decode attempt"); + } + return value; + } + + public static long decodeLong(byte[] data, int index) { + + long value = 0; + + if (data[index] == 0x00) { + throw new RuntimeException("not a number"); + } else if ((data[index] & 0xFF) < OFFSET_SHORT_ITEM) { + + return data[index]; + + } else if ((data[index] & 0xFF) <= OFFSET_SHORT_ITEM + Long.BYTES) { + + byte length = (byte) (data[index] - OFFSET_SHORT_ITEM); + byte pow = (byte) (length - 1); + for (int i = 1; i <= length; ++i) { + // << (8 * pow) == bit shift to 0 (*1), 8 (*256) , 16 (*65..).. + value += (long) (data[index + i] & 0xFF) << (8 * pow); + pow--; + } + } else { + + // If there are more than 8 bytes, it is not going + // to decode properly into a long. + throw new RuntimeException("wrong decode attempt"); + } + return value; + } + + private static String decodeStringItem(byte[] data, int index) { + + final byte[] valueBytes = decodeItemBytes(data, index); + + if (valueBytes.length == 0) { + // shortcut + return ""; + } else { + return new String(valueBytes); + } + } + + public static BigInteger decodeBigInteger(byte[] data, int index) { + + final byte[] valueBytes = decodeItemBytes(data, index); + + if (valueBytes.length == 0) { + // shortcut + return BigInteger.ZERO; + } else { + BigInteger res = new BigInteger(1, valueBytes); + return res; + } + } + + private static byte[] decodeByteArray(byte[] data, int index) { + + return decodeItemBytes(data, index); + } + + private static int nextItemLength(byte[] data, int index) { + + if (index >= data.length) { + return -1; + } + // [0xf8, 0xff] + if ((data[index] & 0xFF) > OFFSET_LONG_LIST) { + byte lengthOfLength = (byte) (data[index] - OFFSET_LONG_LIST); + + return calcLength(lengthOfLength, data, index); + } + // [0xc0, 0xf7] + if ((data[index] & 0xFF) >= OFFSET_SHORT_LIST + && (data[index] & 0xFF) <= OFFSET_LONG_LIST) { + + return (byte) ((data[index] & 0xFF) - OFFSET_SHORT_LIST); + } + // [0xb8, 0xbf] + if ((data[index] & 0xFF) > OFFSET_LONG_ITEM + && (data[index] & 0xFF) < OFFSET_SHORT_LIST) { + + byte lengthOfLength = (byte) (data[index] - OFFSET_LONG_ITEM); + return calcLength(lengthOfLength, data, index); + } + // [0x81, 0xb7] + if ((data[index] & 0xFF) > OFFSET_SHORT_ITEM + && (data[index] & 0xFF) <= OFFSET_LONG_ITEM) { + return (byte) ((data[index] & 0xFF) - OFFSET_SHORT_ITEM); + } + // [0x00, 0x80] + if ((data[index] & 0xFF) <= OFFSET_SHORT_ITEM) { + return 1; + } + return -1; + } + + public static byte[] decodeIP4Bytes(byte[] data, int index) { + + int offset = 1; + + final byte[] result = new byte[4]; + for (int i = 0; i < 4; i++) { + result[i] = decodeOneByteItem(data, index + offset); + if ((data[index + offset] & 0xFF) > OFFSET_SHORT_ITEM) { + offset += 2; + } else { + offset += 1; + } + } + + // return IP address + return result; + } + + public static int getFirstListElement(byte[] payload, int pos) { + + if (pos >= payload.length) { + return -1; + } + + // [0xf8, 0xff] + if ((payload[pos] & 0xFF) > OFFSET_LONG_LIST) { + byte lengthOfLength = (byte) (payload[pos] - OFFSET_LONG_LIST); + return pos + lengthOfLength + 1; + } + // [0xc0, 0xf7] + if ((payload[pos] & 0xFF) >= OFFSET_SHORT_LIST + && (payload[pos] & 0xFF) <= OFFSET_LONG_LIST) { + return pos + 1; + } + // [0xb8, 0xbf] + if ((payload[pos] & 0xFF) > OFFSET_LONG_ITEM + && (payload[pos] & 0xFF) < OFFSET_SHORT_LIST) { + byte lengthOfLength = (byte) (payload[pos] - OFFSET_LONG_ITEM); + return pos + lengthOfLength + 1; + } + return -1; + } + + public static int getNextElementIndex(byte[] payload, int pos) { + + if (pos >= payload.length) { + return -1; + } + + // [0xf8, 0xff] + if ((payload[pos] & 0xFF) > OFFSET_LONG_LIST) { + byte lengthOfLength = (byte) (payload[pos] - OFFSET_LONG_LIST); + int length = calcLength(lengthOfLength, payload, pos); + return pos + lengthOfLength + length + 1; + } + // [0xc0, 0xf7] + if ((payload[pos] & 0xFF) >= OFFSET_SHORT_LIST + && (payload[pos] & 0xFF) <= OFFSET_LONG_LIST) { + + byte length = (byte) ((payload[pos] & 0xFF) - OFFSET_SHORT_LIST); + return pos + 1 + length; + } + // [0xb8, 0xbf] + if ((payload[pos] & 0xFF) > OFFSET_LONG_ITEM + && (payload[pos] & 0xFF) < OFFSET_SHORT_LIST) { + + byte lengthOfLength = (byte) (payload[pos] - OFFSET_LONG_ITEM); + int length = calcLength(lengthOfLength, payload, pos); + return pos + lengthOfLength + length + 1; + } + // [0x81, 0xb7] + if ((payload[pos] & 0xFF) > OFFSET_SHORT_ITEM + && (payload[pos] & 0xFF) <= OFFSET_LONG_ITEM) { + + byte length = (byte) ((payload[pos] & 0xFF) - OFFSET_SHORT_ITEM); + return pos + 1 + length; + } + // []0x80] + if ((payload[pos] & 0xFF) == OFFSET_SHORT_ITEM) { + return pos + 1; + } + // [0x00, 0x7f] + if ((payload[pos] & 0xFF) < OFFSET_SHORT_ITEM) { + return pos + 1; + } + return -1; + } + + /** + * Parse length of long item or list. RLP supports lengths with up to 8 bytes long, but due to + * java limitation it returns either encoded length or {@link Integer#MAX_VALUE} in case if + * encoded length is greater + * + * @param lengthOfLength length of length in bytes + * @param msgData message + * @param pos position to parse from + * @return calculated length + */ + private static int calcLength(int lengthOfLength, byte[] msgData, int pos) { + byte pow = (byte) (lengthOfLength - 1); + int length = 0; + for (int i = 1; i <= lengthOfLength; ++i) { + + int bt = msgData[pos + i] & 0xFF; + int shift = 8 * pow; + + // no leading zeros are acceptable + if (bt == 0 && length == 0) { + throw new RuntimeException("RLP length contains leading zeros"); + } + + // return MAX_VALUE if index of highest bit is more than 31 + if (32 - Integer.numberOfLeadingZeros(bt) + shift > 31) { + return Integer.MAX_VALUE; + } + + length += bt << shift; + pow--; + } + + // check that length is in payload bounds + verifyLength(length, msgData.length - pos - lengthOfLength); + + return length; + } + + public static byte getCommandCode(byte[] data) { + int index = getFirstListElement(data, 0); + final byte command = data[index]; + return ((command & 0xFF) == OFFSET_SHORT_ITEM) ? 0 : command; + } + + /** + * Parse wire byte[] message into RLP elements + * + * @param msgData - raw RLP data + * @param depthLimit - limits depth of decoding + * @return rlpList - outcome of recursive RLP structure + */ + public static RLPList decode2(byte[] msgData, int depthLimit) { + if (depthLimit < 1) { + throw new RuntimeException("Depth limit should be 1 or higher"); + } + RLPList rlpList = new RLPList(); + fullTraverse(msgData, 0, 0, msgData.length, rlpList, depthLimit); + return rlpList; + } + + /** + * Parse wire byte[] message into RLP elements + * + * @param msgData - raw RLP data + * @return rlpList - outcome of recursive RLP structure + */ + public static RLPList decode2(byte[] msgData) { + RLPList rlpList = new RLPList(); + fullTraverse(msgData, 0, 0, msgData.length, rlpList, Integer.MAX_VALUE); + return rlpList; + } + + /** + * Decodes RLP with list without going deep after 1st level list (actually, 2nd as 1st level is + * wrap only) + * + * So assuming you've packed several byte[] with {@link #encodeList(byte[]...)}, you could use + * this method to unpack them, getting RLPList with RLPItem's holding byte[] inside + * + * @param msgData rlp data + * @return list of RLPItems + */ + public static RLPList unwrapList(byte[] msgData) { + return (RLPList) decode2(msgData, 2).get(0); + } + + public static RLPElement decode2OneItem(byte[] msgData, int startPos) { + RLPList rlpList = new RLPList(); + fullTraverse(msgData, 0, startPos, startPos + 1, rlpList, Integer.MAX_VALUE); + return rlpList.get(0); + } + + /** + * Get exactly one message payload + */ + static void fullTraverse(byte[] msgData, int level, int startPos, + int endPos, RLPList rlpList, int depth) { + if (level > MAX_DEPTH) { + throw new RuntimeException( + String.format("Error: Traversing over max RLP depth (%s)", MAX_DEPTH)); + } + + try { + if (msgData == null || msgData.length == 0) { + return; + } + int pos = startPos; + + while (pos < endPos) { + + logger.debug("fullTraverse: level: " + level + " startPos: " + pos + " endPos: " + endPos); + + // It's a list with a payload more than 55 bytes + // data[0] - 0xF7 = how many next bytes allocated + // for the length of the list + if ((msgData[pos] & 0xFF) > OFFSET_LONG_LIST) { + + byte lengthOfLength = (byte) (msgData[pos] - OFFSET_LONG_LIST); + int length = calcLength(lengthOfLength, msgData, pos); + + if (length < SIZE_THRESHOLD) { + throw new RuntimeException("Short list has been encoded as long list"); + } + + // check that length is in payload bounds + verifyLength(length, msgData.length - pos - lengthOfLength); + + byte[] rlpData = new byte[lengthOfLength + length + 1]; + System.arraycopy(msgData, pos, rlpData, 0, lengthOfLength + + length + 1); + + if (level + 1 < depth) { + RLPList newLevelList = new RLPList(); + newLevelList.setRLPData(rlpData); + + fullTraverse(msgData, level + 1, pos + lengthOfLength + 1, + pos + lengthOfLength + length + 1, newLevelList, depth); + rlpList.add(newLevelList); + } else { + rlpList.add(new RLPItem(rlpData)); + } + + pos += lengthOfLength + length + 1; + continue; + } + // It's a list with a payload less than 55 bytes + if ((msgData[pos] & 0xFF) >= OFFSET_SHORT_LIST + && (msgData[pos] & 0xFF) <= OFFSET_LONG_LIST) { + + byte length = (byte) ((msgData[pos] & 0xFF) - OFFSET_SHORT_LIST); + + byte[] rlpData = new byte[length + 1]; + System.arraycopy(msgData, pos, rlpData, 0, length + 1); + + if (level + 1 < depth) { + RLPList newLevelList = new RLPList(); + newLevelList.setRLPData(rlpData); + + if (length > 0) { + fullTraverse(msgData, level + 1, pos + 1, pos + length + 1, newLevelList, depth); + } + rlpList.add(newLevelList); + } else { + rlpList.add(new RLPItem(rlpData)); + } + + pos += 1 + length; + continue; + } + // It's an item with a payload more than 55 bytes + // data[0] - 0xB7 = how much next bytes allocated for + // the length of the string + if ((msgData[pos] & 0xFF) > OFFSET_LONG_ITEM + && (msgData[pos] & 0xFF) < OFFSET_SHORT_LIST) { + + byte lengthOfLength = (byte) (msgData[pos] - OFFSET_LONG_ITEM); + int length = calcLength(lengthOfLength, msgData, pos); + + if (length < SIZE_THRESHOLD) { + throw new RuntimeException("Short item has been encoded as long item"); + } + + // check that length is in payload bounds + verifyLength(length, msgData.length - pos - lengthOfLength); + + // now we can parse an item for data[1]..data[length] + byte[] item = new byte[length]; + System.arraycopy(msgData, pos + lengthOfLength + 1, item, + 0, length); + + RLPItem rlpItem = new RLPItem(item); + rlpList.add(rlpItem); + pos += lengthOfLength + length + 1; + + continue; + } + // It's an item less than 55 bytes long, + // data[0] - 0x80 == length of the item + if ((msgData[pos] & 0xFF) > OFFSET_SHORT_ITEM + && (msgData[pos] & 0xFF) <= OFFSET_LONG_ITEM) { + + byte length = (byte) ((msgData[pos] & 0xFF) - OFFSET_SHORT_ITEM); + + byte[] item = new byte[length]; + System.arraycopy(msgData, pos + 1, item, 0, length); + + if (length == 1 && (item[0] & 0xFF) < OFFSET_SHORT_ITEM) { + throw new RuntimeException("Single byte has been encoded as byte string"); + } + + RLPItem rlpItem = new RLPItem(item); + rlpList.add(rlpItem); + pos += 1 + length; + + continue; + } + // null item + if ((msgData[pos] & 0xFF) == OFFSET_SHORT_ITEM) { + byte[] item = ByteUtil.EMPTY_BYTE_ARRAY; + RLPItem rlpItem = new RLPItem(item); + rlpList.add(rlpItem); + pos += 1; + continue; + } + // single byte item + if ((msgData[pos] & 0xFF) < OFFSET_SHORT_ITEM) { + + byte[] item = {(byte) (msgData[pos] & 0xFF)}; + + RLPItem rlpItem = new RLPItem(item); + rlpList.add(rlpItem); + pos += 1; + } + } + } catch (Exception e) { + throw new RuntimeException( + "RLP wrong encoding (" + Hex.toHexString(msgData, startPos, endPos - startPos) + ")", e); + } catch (OutOfMemoryError e) { + throw new RuntimeException("Invalid RLP (excessive mem allocation while parsing) (" + Hex + .toHexString(msgData, startPos, endPos - startPos) + ")", e); + } + } + + /** + * Compares supplied length information with maximum possible + * + * @param suppliedLength Length info from header + * @param availableLength Length of remaining object + * @throws RuntimeException if supplied length is bigger than available + */ + private static void verifyLength(int suppliedLength, int availableLength) { + if (suppliedLength > availableLength) { + throw new RuntimeException(String.format("Length parsed from RLP (%s bytes) is greater " + + "than possible size of data (%s bytes)", suppliedLength, availableLength)); + } + } + + /** + * Reads any RLP encoded byte-array and returns all objects as byte-array or list of byte-arrays + * + * @param data RLP encoded byte-array + * @param pos position in the array to start reading + * @return DecodeResult encapsulates the decoded items as a single Object and the final read + * position + */ + public static DecodeResult decode(byte[] data, int pos) { + if (data == null || data.length < 1) { + return null; + } + int prefix = data[pos] & 0xFF; + if (prefix == OFFSET_SHORT_ITEM) { // 0x80 + return new DecodeResult(pos + 1, ""); // means no length or 0 + } else if (prefix < OFFSET_SHORT_ITEM) { // [0x00, 0x7f] + return new DecodeResult(pos + 1, new byte[]{data[pos]}); // byte is its own RLP encoding + } else if (prefix <= OFFSET_LONG_ITEM) { // [0x81, 0xb7] + int len = prefix - OFFSET_SHORT_ITEM; // length of the encoded bytes + return new DecodeResult(pos + 1 + len, copyOfRange(data, pos + 1, pos + 1 + len)); + } else if (prefix < OFFSET_SHORT_LIST) { // [0xb8, 0xbf] + int lenlen = prefix - OFFSET_LONG_ITEM; // length of length the encoded bytes + int lenbytes = byteArrayToInt( + copyOfRange(data, pos + 1, pos + 1 + lenlen)); // length of encoded bytes + // check that length is in payload bounds + verifyLength(lenbytes, data.length - pos - 1 - lenlen); + return new DecodeResult(pos + 1 + lenlen + lenbytes, + copyOfRange(data, pos + 1 + lenlen, pos + 1 + lenlen + + lenbytes)); + } else if (prefix <= OFFSET_LONG_LIST) { // [0xc0, 0xf7] + int len = prefix - OFFSET_SHORT_LIST; // length of the encoded list + int prevPos = pos; + pos++; + return decodeList(data, pos, len); + } else if (prefix <= 0xFF) { // [0xf8, 0xff] + int lenlen = prefix - OFFSET_LONG_LIST; // length of length the encoded list + int lenlist = byteArrayToInt( + copyOfRange(data, pos + 1, pos + 1 + lenlen)); // length of encoded bytes + pos = pos + lenlen + 1; // start at position of first element in list + int prevPos = lenlist; + return decodeList(data, pos, lenlist); + } else { + throw new RuntimeException( + "Only byte values between 0x00 and 0xFF are supported, but got: " + prefix); + } + } + + public static final class LList { + + private final byte[] rlp; + private final int[] offsets = new int[32]; + private final int[] lens = new int[32]; + private int cnt; + + public LList(byte[] rlp) { + this.rlp = rlp; + } + + public byte[] getEncoded() { + byte encoded[][] = new byte[cnt][]; + for (int i = 0; i < cnt; i++) { + encoded[i] = encodeElement(getBytes(i)); + } + return encodeList(encoded); + } + + public void add(int off, int len, boolean isList) { + offsets[cnt] = off; + lens[cnt] = isList ? (-1 - len) : len; + cnt++; + } + + public byte[] getBytes(int idx) { + int len = lens[idx]; + len = len < 0 ? (-len - 1) : len; + byte[] ret = new byte[len]; + System.arraycopy(rlp, offsets[idx], ret, 0, len); + return ret; + } + + public LList getList(int idx) { + return decodeLazyList(rlp, offsets[idx], -lens[idx] - 1); + } + + public boolean isList(int idx) { + return lens[idx] < 0; + } + + public int size() { + return cnt; + } + } + + public static LList decodeLazyList(byte[] data) { + LList lList = decodeLazyList(data, 0, data.length); + return lList == null ? null : lList.getList(0); + } + + public static LList decodeLazyList(byte[] data, int pos, int length) { + if (data == null || data.length < 1) { + return null; + } + LList ret = new LList(data); + int end = pos + length; + + while (pos < end) { + int prefix = data[pos] & 0xFF; + if (prefix == OFFSET_SHORT_ITEM) { // 0x80 + ret.add(pos, 0, false); // means no length or 0 + pos++; + } else if (prefix < OFFSET_SHORT_ITEM) { // [0x00, 0x7f] + ret.add(pos, 1, false); // means no length or 0 + pos++; + } else if (prefix <= OFFSET_LONG_ITEM) { // [0x81, 0xb7] + int len = prefix - OFFSET_SHORT_ITEM; // length of the encoded bytes + ret.add(pos + 1, len, false); + pos += len + 1; + } else if (prefix < OFFSET_SHORT_LIST) { // [0xb8, 0xbf] + int lenlen = prefix - OFFSET_LONG_ITEM; // length of length the encoded bytes + int lenbytes = byteArrayToInt( + copyOfRange(data, pos + 1, pos + 1 + lenlen)); // length of encoded bytes + // check that length is in payload bounds + verifyLength(lenbytes, data.length - pos - 1 - lenlen); + ret.add(pos + 1 + lenlen, lenbytes, false); + pos += 1 + lenlen + lenbytes; + } else if (prefix <= OFFSET_LONG_LIST) { // [0xc0, 0xf7] + int len = prefix - OFFSET_SHORT_LIST; // length of the encoded list + ret.add(pos + 1, len, true); + pos += 1 + len; + } else if (prefix <= 0xFF) { // [0xf8, 0xff] + int lenlen = prefix - OFFSET_LONG_LIST; // length of length the encoded list + int lenlist = byteArrayToInt( + copyOfRange(data, pos + 1, pos + 1 + lenlen)); // length of encoded bytes + // check that length is in payload bounds + verifyLength(lenlist, data.length - pos - 1 - lenlen); + ret.add(pos + 1 + lenlen, lenlist, true); + pos += 1 + lenlen + lenlist; // start at position of first element in list + } else { + throw new RuntimeException( + "Only byte values between 0x00 and 0xFF are supported, but got: " + prefix); + } + } + return ret; + } + + + private static DecodeResult decodeList(byte[] data, int pos, int len) { + // check that length is in payload bounds + verifyLength(len, data.length - pos); + int prevPos; + List slice = new ArrayList<>(); + for (int i = 0; i < len; ) { + // Get the next item in the data list and append it + DecodeResult result = decode(data, pos); + slice.add(result.getDecoded()); + // Increment pos by the amount bytes in the previous read + prevPos = result.getPos(); + i += (prevPos - pos); + pos = prevPos; + } + return new DecodeResult(pos, slice.toArray()); + } + + /* ****************************************************** + * ENCODING * + * ******************************************************/ + + /** + * Turn Object into its RLP encoded equivalent of a byte-array Support for String, Integer, + * BigInteger and Lists of any of these types. + * + * @param input as object or List of objects + * @return byte[] RLP encoded + */ + public static byte[] encode(Object input) { + Value val = new Value(input); + if (val.isList()) { + List inputArray = val.asList(); + if (inputArray.isEmpty()) { + return encodeLength(inputArray.size(), OFFSET_SHORT_LIST); + } + byte[] output = ByteUtil.EMPTY_BYTE_ARRAY; + for (Object object : inputArray) { + output = concatenate(output, encode(object)); + } + byte[] prefix = encodeLength(output.length, OFFSET_SHORT_LIST); + return concatenate(prefix, output); + } else { + byte[] inputAsBytes = toBytes(input); + if (inputAsBytes.length == 1 && (inputAsBytes[0] & 0xff) <= 0x80) { + return inputAsBytes; + } else { + byte[] firstByte = encodeLength(inputAsBytes.length, OFFSET_SHORT_ITEM); + return concatenate(firstByte, inputAsBytes); + } + } + } + + /** + * Integer limitation goes up to 2^31-1 so length can never be bigger than MAX_ITEM_LENGTH + */ + public static byte[] encodeLength(int length, int offset) { + if (length < SIZE_THRESHOLD) { + byte firstByte = (byte) (length + offset); + return new byte[]{firstByte}; + } else if (length < MAX_ITEM_LENGTH) { + byte[] binaryLength; + if (length > 0xFF) { + binaryLength = intToBytesNoLeadZeroes(length); + } else { + binaryLength = new byte[]{(byte) length}; + } + byte firstByte = (byte) (binaryLength.length + offset + SIZE_THRESHOLD - 1); + return concatenate(new byte[]{firstByte}, binaryLength); + } else { + throw new RuntimeException("Input too long"); + } + } + + public static byte[] encodeByte(byte singleByte) { + if ((singleByte & 0xFF) == 0) { + return new byte[]{(byte) OFFSET_SHORT_ITEM}; + } else if ((singleByte & 0xFF) <= 0x7F) { + return new byte[]{singleByte}; + } else { + return new byte[]{(byte) (OFFSET_SHORT_ITEM + 1), singleByte}; + } + } + + public static byte[] encodeShort(short singleShort) { + + if ((singleShort & 0xFF) == singleShort) { + return encodeByte((byte) singleShort); + } else { + return new byte[]{(byte) (OFFSET_SHORT_ITEM + 2), + (byte) (singleShort >> 8 & 0xFF), + (byte) (singleShort >> 0 & 0xFF)}; + } + } + + public static byte[] encodeInt(int singleInt) { + + if ((singleInt & 0xFF) == singleInt) { + return encodeByte((byte) singleInt); + } else if ((singleInt & 0xFFFF) == singleInt) { + return encodeShort((short) singleInt); + } else if ((singleInt & 0xFFFFFF) == singleInt) { + return new byte[]{(byte) (OFFSET_SHORT_ITEM + 3), + (byte) (singleInt >>> 16), + (byte) (singleInt >>> 8), + (byte) singleInt}; + } else { + return new byte[]{(byte) (OFFSET_SHORT_ITEM + 4), + (byte) (singleInt >>> 24), + (byte) (singleInt >>> 16), + (byte) (singleInt >>> 8), + (byte) singleInt}; + } + } + + public static byte[] encodeString(String srcString) { + return encodeElement(srcString.getBytes()); + } + + public static byte[] encodeBigInteger(BigInteger srcBigInteger) { + if (srcBigInteger.compareTo(BigInteger.ZERO) < 0) { + throw new RuntimeException("negative numbers are not allowed"); + } + + if (srcBigInteger.equals(BigInteger.ZERO)) { + return encodeByte((byte) 0); + } else { + return encodeElement(asUnsignedByteArray(srcBigInteger)); + } + } + + public static byte[] encodeElement(byte[] srcData) { + + // [0x80] + if (isNullOrZeroArray(srcData)) { + return new byte[]{(byte) OFFSET_SHORT_ITEM}; + + // [0x00] + } else if (isSingleZero(srcData)) { + return srcData; + + // [0x01, 0x7f] - single byte, that byte is its own RLP encoding + } else if (srcData.length == 1 && (srcData[0] & 0xFF) < 0x80) { + return srcData; + + // [0x80, 0xb7], 0 - 55 bytes + } else if (srcData.length < SIZE_THRESHOLD) { + // length = 8X + byte length = (byte) (OFFSET_SHORT_ITEM + srcData.length); + byte[] data = Arrays.copyOf(srcData, srcData.length + 1); + System.arraycopy(data, 0, data, 1, srcData.length); + data[0] = length; + + return data; + // [0xb8, 0xbf], 56+ bytes + } else { + // length of length = BX + // prefix = [BX, [length]] + int tmpLength = srcData.length; + byte lengthOfLength = 0; + while (tmpLength != 0) { + ++lengthOfLength; + tmpLength = tmpLength >> 8; + } + + // set length Of length at first byte + byte[] data = new byte[1 + lengthOfLength + srcData.length]; + data[0] = (byte) (OFFSET_LONG_ITEM + lengthOfLength); + + // copy length after first byte + tmpLength = srcData.length; + for (int i = lengthOfLength; i > 0; --i) { + data[i] = (byte) (tmpLength & 0xFF); + tmpLength = tmpLength >> 8; + } + + // at last copy the number bytes after its length + System.arraycopy(srcData, 0, data, 1 + lengthOfLength, srcData.length); + + return data; + } + } + + public static int calcElementPrefixSize(byte[] srcData) { + + if (isNullOrZeroArray(srcData)) { + return 0; + } else if (isSingleZero(srcData)) { + return 0; + } else if (srcData.length == 1 && (srcData[0] & 0xFF) < 0x80) { + return 0; + } else if (srcData.length < SIZE_THRESHOLD) { + return 1; + } else { + // length of length = BX + // prefix = [BX, [length]] + int tmpLength = srcData.length; + byte byteNum = 0; + while (tmpLength != 0) { + ++byteNum; + tmpLength = tmpLength >> 8; + } + + return 1 + byteNum; + } + } + + + public static byte[] encodeListHeader(int size) { + + if (size == 0) { + return new byte[]{(byte) OFFSET_SHORT_LIST}; + } + + int totalLength = size; + + byte[] header; + if (totalLength < SIZE_THRESHOLD) { + + header = new byte[1]; + header[0] = (byte) (OFFSET_SHORT_LIST + totalLength); + } else { + // length of length = BX + // prefix = [BX, [length]] + int tmpLength = totalLength; + byte byteNum = 0; + while (tmpLength != 0) { + ++byteNum; + tmpLength = tmpLength >> 8; + } + tmpLength = totalLength; + + byte[] lenBytes = new byte[byteNum]; + for (int i = 0; i < byteNum; ++i) { + lenBytes[byteNum - 1 - i] = (byte) ((tmpLength >> (8 * i)) & 0xFF); + } + // first byte = F7 + bytes.length + header = new byte[1 + lenBytes.length]; + header[0] = (byte) (OFFSET_LONG_LIST + byteNum); + System.arraycopy(lenBytes, 0, header, 1, lenBytes.length); + + } + + return header; + } + + + public static byte[] encodeLongElementHeader(int length) { + + if (length < SIZE_THRESHOLD) { + + if (length == 0) { + return new byte[]{(byte) 0x80}; + } else { + return new byte[]{(byte) (0x80 + length)}; + } + + } else { + + // length of length = BX + // prefix = [BX, [length]] + int tmpLength = length; + byte byteNum = 0; + while (tmpLength != 0) { + ++byteNum; + tmpLength = tmpLength >> 8; + } + + byte[] lenBytes = new byte[byteNum]; + for (int i = 0; i < byteNum; ++i) { + lenBytes[byteNum - 1 - i] = (byte) ((length >> (8 * i)) & 0xFF); + } + + // first byte = F7 + bytes.length + byte[] header = new byte[1 + lenBytes.length]; + header[0] = (byte) (OFFSET_LONG_ITEM + byteNum); + System.arraycopy(lenBytes, 0, header, 1, lenBytes.length); + + return header; + } + } + + public static byte[] encodeSet(Set data) { + + int dataLength = 0; + Set encodedElements = new HashSet<>(); + for (ByteArrayWrapper element : data) { + + byte[] encodedElement = RLP.encodeElement(element.getData()); + dataLength += encodedElement.length; + encodedElements.add(encodedElement); + } + + byte[] listHeader = encodeListHeader(dataLength); + + byte[] output = new byte[listHeader.length + dataLength]; + + System.arraycopy(listHeader, 0, output, 0, listHeader.length); + + int cummStart = listHeader.length; + for (byte[] element : encodedElements) { + System.arraycopy(element, 0, output, cummStart, element.length); + cummStart += element.length; + } + + return output; + } + + /** + * A handy shortcut for {@link #encodeElement(byte[])} + {@link #encodeList(byte[]...)} + *

+ * Encodes each data element and wraps them all into a list. + */ + public static byte[] wrapList(byte[]... data) { + byte[][] elements = new byte[data.length][]; + for (int i = 0; i < data.length; i++) { + elements[i] = encodeElement(data[i]); + } + return encodeList(elements); + } + + public static byte[] encodeList(byte[]... elements) { + + if (elements == null) { + return new byte[]{(byte) OFFSET_SHORT_LIST}; + } + + int totalLength = 0; + for (byte[] element1 : elements) { + totalLength += element1.length; + } + + byte[] data; + int copyPos; + if (totalLength < SIZE_THRESHOLD) { + + data = new byte[1 + totalLength]; + data[0] = (byte) (OFFSET_SHORT_LIST + totalLength); + copyPos = 1; + } else { + // length of length = BX + // prefix = [BX, [length]] + int tmpLength = totalLength; + byte byteNum = 0; + while (tmpLength != 0) { + ++byteNum; + tmpLength = tmpLength >> 8; + } + tmpLength = totalLength; + byte[] lenBytes = new byte[byteNum]; + for (int i = 0; i < byteNum; ++i) { + lenBytes[byteNum - 1 - i] = (byte) ((tmpLength >> (8 * i)) & 0xFF); + } + // first byte = F7 + bytes.length + data = new byte[1 + lenBytes.length + totalLength]; + data[0] = (byte) (OFFSET_LONG_LIST + byteNum); + System.arraycopy(lenBytes, 0, data, 1, lenBytes.length); + + copyPos = lenBytes.length + 1; + } + for (byte[] element : elements) { + System.arraycopy(element, 0, data, copyPos, element.length); + copyPos += element.length; + } + return data; + } + + public static byte[] encodeList(Object... elements) { + + if (elements == null) { + return new byte[]{(byte) OFFSET_SHORT_LIST}; + } + + int totalLength = 0; + for (Object element1 : elements) { + byte[] value = (byte[]) element1; + totalLength += value.length; + } + + byte[] data; + int copyPos; + if (totalLength < SIZE_THRESHOLD) { + + data = new byte[1 + totalLength]; + data[0] = (byte) (OFFSET_SHORT_LIST + totalLength); + copyPos = 1; + } else { + // length of length = BX + // prefix = [BX, [length]] + int tmpLength = totalLength; + byte byteNum = 0; + while (tmpLength != 0) { + ++byteNum; + tmpLength = tmpLength >> 8; + } + tmpLength = totalLength; + byte[] lenBytes = new byte[byteNum]; + for (int i = 0; i < byteNum; ++i) { + lenBytes[byteNum - 1 - i] = (byte) ((tmpLength >> (8 * i)) & 0xFF); + } + // first byte = F7 + bytes.length + data = new byte[1 + lenBytes.length + totalLength]; + data[0] = (byte) (OFFSET_LONG_LIST + byteNum); + System.arraycopy(lenBytes, 0, data, 1, lenBytes.length); + + copyPos = lenBytes.length + 1; + } + for (Object object : elements) { + byte[] element = (byte[]) object; + System.arraycopy(element, 0, data, copyPos, element.length); + copyPos += element.length; + } + return data; + } + + /* + * Utility function to convert Objects into byte arrays + */ + private static byte[] toBytes(Object input) { + if (input instanceof byte[]) { + return (byte[]) input; + } else if (input instanceof String) { + String inputString = (String) input; + return inputString.getBytes(); + } else if (input instanceof Long) { + Long inputLong = (Long) input; + return (inputLong == 0) ? ByteUtil.EMPTY_BYTE_ARRAY + : asUnsignedByteArray(BigInteger.valueOf(inputLong)); + } else if (input instanceof Integer) { + Integer inputInt = (Integer) input; + return (inputInt == 0) ? ByteUtil.EMPTY_BYTE_ARRAY + : asUnsignedByteArray(BigInteger.valueOf(inputInt)); + } else if (input instanceof BigInteger) { + BigInteger inputBigInt = (BigInteger) input; + return (inputBigInt.equals(BigInteger.ZERO)) ? ByteUtil.EMPTY_BYTE_ARRAY + : asUnsignedByteArray(inputBigInt); + } else if (input instanceof Value) { + Value val = (Value) input; + return toBytes(val.asObj()); + } + throw new RuntimeException( + "Unsupported type: Only accepting String, Integer and BigInteger for now"); + } + + + public static byte[] decodeItemBytes(byte[] data, int index) { + + final int length = calculateItemLength(data, index); + // [0x80] + if (length == 0) { + + return new byte[0]; + + // [0x00, 0x7f] - single byte with item + } else if ((data[index] & 0xFF) < OFFSET_SHORT_ITEM) { + + byte[] valueBytes = new byte[1]; + System.arraycopy(data, index, valueBytes, 0, 1); + return valueBytes; + + // [0x01, 0xb7] - 1-55 bytes item + } else if ((data[index] & 0xFF) <= OFFSET_LONG_ITEM) { + + byte[] valueBytes = new byte[length]; + System.arraycopy(data, index + 1, valueBytes, 0, length); + return valueBytes; + + // [0xb8, 0xbf] - 56+ bytes item + } else if ((data[index] & 0xFF) > OFFSET_LONG_ITEM + && (data[index] & 0xFF) < OFFSET_SHORT_LIST) { + + byte lengthOfLength = (byte) (data[index] - OFFSET_LONG_ITEM); + byte[] valueBytes = new byte[length]; + System.arraycopy(data, index + 1 + lengthOfLength, valueBytes, 0, length); + return valueBytes; + } else { + throw new RuntimeException("wrong decode attempt"); + } + } + + + private static int calculateItemLength(byte[] data, int index) { + + // [0xb8, 0xbf] - 56+ bytes item + if ((data[index] & 0xFF) > OFFSET_LONG_ITEM + && (data[index] & 0xFF) < OFFSET_SHORT_LIST) { + + byte lengthOfLength = (byte) (data[index] - OFFSET_LONG_ITEM); + return calcLength(lengthOfLength, data, index); + + // [0x81, 0xb7] - 0-55 bytes item + } else if ((data[index] & 0xFF) > OFFSET_SHORT_ITEM + && (data[index] & 0xFF) <= OFFSET_LONG_ITEM) { + + return (byte) (data[index] - OFFSET_SHORT_ITEM); + + // [0x80] - item = 0 itself + } else if ((data[index] & 0xFF) == OFFSET_SHORT_ITEM) { + + return (byte) 0; + + // [0x00, 0x7f] - 1 byte item, no separate length representation + } else if ((data[index] & 0xFF) < OFFSET_SHORT_ITEM) { + + return (byte) 1; + + } else { + throw new RuntimeException("wrong decode attempt"); + } + } +} diff --git a/src/main/java/org/tron/core/capsule/utils/RLPElement.java b/src/main/java/org/tron/core/capsule/utils/RLPElement.java new file mode 100644 index 00000000000..b2af70fa215 --- /dev/null +++ b/src/main/java/org/tron/core/capsule/utils/RLPElement.java @@ -0,0 +1,11 @@ +package org.tron.core.capsule.utils; + +import java.io.Serializable; + +/** + * Wrapper class for decoded elements from an RLP encoded byte array. + */ +public interface RLPElement extends Serializable { + + byte[] getRLPData(); +} diff --git a/src/main/java/org/tron/core/capsule/utils/RLPItem.java b/src/main/java/org/tron/core/capsule/utils/RLPItem.java new file mode 100644 index 00000000000..8c8a4357b4b --- /dev/null +++ b/src/main/java/org/tron/core/capsule/utils/RLPItem.java @@ -0,0 +1,20 @@ + +package org.tron.core.capsule.utils; + +/** + */ +public class RLPItem implements RLPElement { + + private final byte[] rlpData; + + public RLPItem(byte[] rlpData) { + this.rlpData = rlpData; + } + + public byte[] getRLPData() { + if (rlpData.length == 0) { + return null; + } + return rlpData; + } +} diff --git a/src/main/java/org/tron/core/capsule/utils/RLPList.java b/src/main/java/org/tron/core/capsule/utils/RLPList.java new file mode 100644 index 00000000000..c6a4f028b68 --- /dev/null +++ b/src/main/java/org/tron/core/capsule/utils/RLPList.java @@ -0,0 +1,39 @@ + +package org.tron.core.capsule.utils; + +import java.util.ArrayList; +import org.tron.common.utils.ByteUtil; + +/** + */ +public class RLPList extends ArrayList implements RLPElement { + + byte[] rlpData; + + public void setRLPData(byte[] rlpData) { + this.rlpData = rlpData; + } + + public byte[] getRLPData() { + return rlpData; + } + + public static void recursivePrint(RLPElement element) { + + if (element == null) { + throw new RuntimeException("RLPElement object can't be null"); + } + if (element instanceof RLPList) { + + RLPList rlpList = (RLPList) element; + System.out.print("["); + for (RLPElement singleElement : rlpList) { + recursivePrint(singleElement); + } + System.out.print("]"); + } else { + String hex = ByteUtil.toHexString(element.getRLPData()); + System.out.print(hex + ", "); + } + } +} diff --git a/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java b/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java index f054b92dcf8..c8a4f2608cd 100644 --- a/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java +++ b/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java @@ -18,6 +18,7 @@ import com.google.protobuf.ByteString; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; +import org.tron.core.Constant; import org.tron.core.Wallet; import org.tron.core.capsule.TransactionCapsule; import org.tron.protos.Contract.TransferContract; @@ -43,22 +44,12 @@ public static Transaction newGenesisTransaction(byte[] key, long value) Contract.ContractType.TransferContract).getInstance(); } - /** - * checkBalance. - */ - private static boolean checkBalance(long totalBalance, long totalSpent) { - return totalBalance == totalSpent; - } - public static boolean validAccountName(byte[] accountName) { if (ArrayUtils.isEmpty(accountName)) { return true; //accountname can empty } - if (accountName.length > 200) { - return false; - } - // other rules. - return true; + + return accountName.length <= 200; } public static boolean validAccountId(byte[] accountId) { @@ -128,22 +119,15 @@ public static boolean validAssetDescription(byte[] description) { if (ArrayUtils.isEmpty(description)) { return true; //description can empty } - if (description.length > 200) { - return false; - } - // other rules. - return true; + + return description.length <= 200; } public static boolean validUrl(byte[] url) { if (ArrayUtils.isEmpty(url)) { return false; } - if (url.length > 256) { - return false; - } - // other rules. - return true; + return url.length <= 256; } public static boolean isNumber(byte[] id) { @@ -155,12 +139,10 @@ public static boolean isNumber(byte[] id) { return false; } } - if (id.length > 1 && id[0] == '0') { - return false; - } - return true; + return !(id.length > 1 && id[0] == '0'); } + /** * Get sender. */ diff --git a/src/main/java/org/tron/core/config/CommonConfig.java b/src/main/java/org/tron/core/config/CommonConfig.java index fb10caba2b6..d007c39564a 100644 --- a/src/main/java/org/tron/core/config/CommonConfig.java +++ b/src/main/java/org/tron/core/config/CommonConfig.java @@ -28,5 +28,4 @@ @ComponentScan(basePackages = "org.tron") public class CommonConfig { - private static CommonConfig defaultInstance; } diff --git a/src/main/java/org/tron/core/config/DefaultConfig.java b/src/main/java/org/tron/core/config/DefaultConfig.java index 3aef308e145..13413ea0d45 100755 --- a/src/main/java/org/tron/core/config/DefaultConfig.java +++ b/src/main/java/org/tron/core/config/DefaultConfig.java @@ -30,10 +30,10 @@ public class DefaultConfig { } @Autowired - ApplicationContext appCtx; + public ApplicationContext appCtx; @Autowired - CommonConfig commonConfig; + public CommonConfig commonConfig; public DefaultConfig() { Thread.setDefaultUncaughtExceptionHandler((t, e) -> logger.error("Uncaught exception", e)); diff --git a/src/main/java/org/tron/core/config/Parameter.java b/src/main/java/org/tron/core/config/Parameter.java index 5d3e52533be..12732495156 100644 --- a/src/main/java/org/tron/core/config/Parameter.java +++ b/src/main/java/org/tron/core/config/Parameter.java @@ -2,77 +2,72 @@ import lombok.Getter; -public interface Parameter { - - interface ChainConstant { - - long TRANSFER_FEE = 0; // free - int WITNESS_STANDBY_LENGTH = 127; - int SOLIDIFIED_THRESHOLD = 70; // 70% - int PRIVATE_KEY_LENGTH = 64; - int MAX_ACTIVE_WITNESS_NUM = 27; - int BLOCK_SIZE = 2_000_000; - int BLOCK_PRODUCED_INTERVAL = 3000; //ms,produce block period, must be divisible by 60. millisecond - long CLOCK_MAX_DELAY = 3600000; // 3600 * 1000 ms - int BLOCK_PRODUCED_TIME_OUT = 50; // 50% - long PRECISION = 1000_000; - long WINDOW_SIZE_MS = 24 * 3600 * 1000L; - long MS_PER_DAY = 24 * 3600 * 1000L; - long MS_PER_YEAR = 365 * 24 * 3600 * 1000L; - - long MAINTENANCE_SKIP_SLOTS = 2; - int SINGLE_REPEAT = 1; - int BLOCK_FILLED_SLOTS_NUMBER = 128; - int MAX_VOTE_NUMBER = 30; - int MAX_FROZEN_NUMBER = 1; - int BLOCK_VERSION = 7; +public class Parameter { + + public class ChainConstant { + public static final long TRANSFER_FEE = 0; // free + public static final int WITNESS_STANDBY_LENGTH = 127; + public static final int SOLIDIFIED_THRESHOLD = 70; // 70% + public static final int PRIVATE_KEY_LENGTH = 64; + public static final int MAX_ACTIVE_WITNESS_NUM = 27; + public static final int BLOCK_SIZE = 2_000_000; + public static final int BLOCK_PRODUCED_INTERVAL = 3000; //ms,produce block period, must be divisible by 60. millisecond + public static final long CLOCK_MAX_DELAY = 3600000; // 3600 * 1000 ms + public static final int BLOCK_PRODUCED_TIME_OUT = 50; // 50% + public static final long PRECISION = 1_000_000; + public static final long WINDOW_SIZE_MS = 24 * 3600 * 1000L; + public static final long MS_PER_YEAR = 365 * 24 * 3600 * 1000L; + public static final long MAINTENANCE_SKIP_SLOTS = 2; + public static final int SINGLE_REPEAT = 1; + public static final int BLOCK_FILLED_SLOTS_NUMBER = 128; + public static final int MAX_VOTE_NUMBER = 30; + public static final int MAX_FROZEN_NUMBER = 1; + public static final int BLOCK_VERSION = 8; } - interface NodeConstant { - - long SYNC_RETURN_BATCH_NUM = 1000; - long SYNC_FETCH_BATCH_NUM = 2000; - long MAX_BLOCKS_IN_PROCESS = 400; - long MAX_BLOCKS_ALREADY_FETCHED = 800; - long MAX_BLOCKS_SYNC_FROM_ONE_PEER = 1000; - long SYNC_CHAIN_LIMIT_NUM = 500; - int MAX_TRANSACTION_PENDING = 2000; + public class NodeConstant { + public static final long SYNC_RETURN_BATCH_NUM = 1000; + public static final long SYNC_FETCH_BATCH_NUM = 2000; + public static final long MAX_BLOCKS_IN_PROCESS = 400; + public static final long MAX_BLOCKS_ALREADY_FETCHED = 800; + public static final long MAX_BLOCKS_SYNC_FROM_ONE_PEER = 1000; + public static final long SYNC_CHAIN_LIMIT_NUM = 500; + public static final int MAX_TRANSACTION_PENDING = 2000; + public static final int MAX_HTTP_CONNECT_NUMBER = 50; } - interface NetConstants { - - long GRPC_IDLE_TIME_OUT = 60000L; - long ADV_TIME_OUT = 20000L; - long SYNC_TIME_OUT = 20000L; - long HEAD_NUM_MAX_DELTA = 1000L; - long HEAD_NUM_CHECK_TIME = 60000L; - int MAX_INVENTORY_SIZE_IN_MINUTES = 2; - long NET_MAX_TRX_PER_SECOND = 700L; - int MAX_BLOCK_FETCH_PER_PEER = 100; - int MAX_TRX_FETCH_PER_PEER = 1000; - int NET_MAX_INV_SIZE_IN_MINUTES = 2; - int MSG_CACHE_DURATION_IN_BLOCKS = 5; + public class NetConstants { + public static final long GRPC_IDLE_TIME_OUT = 60000L; + public static final long ADV_TIME_OUT = 20000L; + public static final long SYNC_TIME_OUT = 5000L; + public static final long HEAD_NUM_MAX_DELTA = 1000L; + public static final long HEAD_NUM_CHECK_TIME = 60000L; + public static final int MAX_INVENTORY_SIZE_IN_MINUTES = 2; + public static final long NET_MAX_TRX_PER_SECOND = 700L; + public static final long MAX_TRX_PER_PEER = 200L; + public static final int NET_MAX_INV_SIZE_IN_MINUTES = 2; + public static final int MSG_CACHE_DURATION_IN_BLOCKS = 5; + public static final int MAX_BLOCK_FETCH_PER_PEER = 100; + public static final int MAX_TRX_FETCH_PER_PEER = 1000; } - interface DatabaseConstants { - - int TRANSACTIONS_COUNT_LIMIT_MAX = 1000; - int ASSET_ISSUE_COUNT_LIMIT_MAX = 1000; - int PROPOSAL_COUNT_LIMIT_MAX = 1000; - int EXCHANGE_COUNT_LIMIT_MAX = 1000; + public class DatabaseConstants { + public static final int TRANSACTIONS_COUNT_LIMIT_MAX = 1000; + public static final int ASSET_ISSUE_COUNT_LIMIT_MAX = 1000; + public static final int PROPOSAL_COUNT_LIMIT_MAX = 1000; + public static final int EXCHANGE_COUNT_LIMIT_MAX = 1000; } - interface AdaptiveResourceLimitConstants { - - int CONTRACT_RATE_NUMERATOR = 99; - int CONTRACT_RATE_DENOMINATOR = 100; - int EXPAND_RATE_NUMERATOR = 1000; - int EXPAND_RATE_DENOMINATOR = 999; - int PERIODS_MS = 60_000; - int LIMIT_MULTIPLIER = 1000; //s + public class AdaptiveResourceLimitConstants { + public static final int CONTRACT_RATE_NUMERATOR = 99; + public static final int CONTRACT_RATE_DENOMINATOR = 100; + public static final int EXPAND_RATE_NUMERATOR = 1000; + public static final int EXPAND_RATE_DENOMINATOR = 999; + public static final int PERIODS_MS = 60_000; + public static final int LIMIT_MULTIPLIER = 1000; //s } - enum ChainParameters { + public enum ChainParameters { MAINTENANCE_TIME_INTERVAL, //ms ,0 ACCOUNT_UPGRADE_COST, //drop ,1 CREATE_ACCOUNT_FEE, //drop ,2 @@ -97,30 +92,23 @@ enum ChainParameters { ALLOW_ADAPTIVE_ENERGY, // 1, 21 UPDATE_ACCOUNT_PERMISSION_FEE, // 100, 22 MULTI_SIGN_FEE, // 1, 23 -// ONE_DAY_NET_LIMIT, -// MAX_FROZEN_TIME, -// MIN_FROZEN_TIME, -// MAX_FROZEN_SUPPLY_NUMBER, -// MAX_FROZEN_SUPPLY_TIME, -// MIN_FROZEN_SUPPLY_TIME, -// WITNESS_ALLOWANCE_FROZEN_TIME, -// PUBLIC_NET_LIMIT, -// FREE_NET_LIMIT, -// TOTAL_NET_LIMIT, -// EXCHANGE_BALANCE_LIMIT, + ALLOW_PROTO_FILTER_NUM, // 1, 24 + ALLOW_ACCOUNT_STATE_ROOT, // 1, 25 + ALLOW_TVM_CONSTANTINOPLE, // 1, 26 } @Deprecated - interface ForkBlockVersionConsts { - - int START_NEW_TRANSACTION = 4; - int ENERGY_LIMIT = 5; + public class ForkBlockVersionConsts { + public static final int START_NEW_TRANSACTION = 4; + public static final int ENERGY_LIMIT = 5; } - enum ForkBlockVersionEnum { + public enum ForkBlockVersionEnum { ENERGY_LIMIT(5), VERSION_3_2_2(6), - VERSION_3_5(7); + VERSION_3_5(7), + VERSION_3_6(8); + @Getter private int value; diff --git a/src/main/java/org/tron/core/config/args/Args.java b/src/main/java/org/tron/core/config/args/Args.java index 03bd05d6969..25c87796bfc 100644 --- a/src/main/java/org/tron/core/config/args/Args.java +++ b/src/main/java/org/tron/core/config/args/Args.java @@ -47,6 +47,7 @@ import org.tron.core.config.Configuration; import org.tron.core.config.Parameter.ChainConstant; import org.tron.core.config.Parameter.NetConstants; +import org.tron.core.config.Parameter.NodeConstant; import org.tron.core.db.AccountStore; import org.tron.core.db.backup.DbBackupConfig; import org.tron.keystore.CipherException; @@ -105,6 +106,11 @@ public class Args { @Parameter(names = {"--long-running-time"}) private int longRunningTime = 10; + @Getter + @Setter + @Parameter(names = {"--max-connect-number"}) + private int maxHttpConnectNumber = 50; + @Getter @Parameter(description = "--seed-nodes") private List seedNodes = new ArrayList<>(); @@ -132,6 +138,10 @@ public class Args { "--storage-db-synchronous"}, description = "Storage db is synchronous or not.(true or flase)") private String storageDbSynchronous = ""; + @Parameter(names = { + "--contract-parse-enable"}, description = "enable contract parses in java-tron or not.(true or flase)") + private String contractParseEnable = ""; + @Parameter(names = {"--storage-index-directory"}, description = "Storage index directory") private String storageIndexDirectory = ""; @@ -230,9 +240,6 @@ public class Args { @Setter private long nodeP2pPingInterval; - // @Getter -// @Setter -// private long syncNodeCount; @Getter @Setter @Parameter(names = {"--save-internaltx"}) @@ -346,6 +353,10 @@ public class Args { @Setter private long allowTvmTransferTrc10; //committee parameter + @Getter + @Setter + private long allowTvmConstantinople; //committee parameter + @Getter @Setter private int tcpNettyWorkThreadNum; @@ -447,6 +458,18 @@ public class Args { @Parameter(names = {"-v", "--version"}, description = "output code version", help = true) private boolean version; + @Getter + @Setter + private long allowProtoFilterNum; + + @Getter + @Setter + private long allowAccountStateRoot; + + @Getter + @Setter + private int validContractProtoThreadNum; + public static void clearParam() { INSTANCE.outputDirectory = "output-directory"; INSTANCE.help = false; @@ -498,6 +521,7 @@ public static void clearParam() { INSTANCE.allowCreationOfContracts = 0; INSTANCE.allowAdaptiveEnergy = 0; INSTANCE.allowTvmTransferTrc10 = 0; + INSTANCE.allowTvmConstantinople = 0; INSTANCE.allowDelegateResource = 0; INSTANCE.allowSameTokenName = 0; INSTANCE.tcpNettyWorkThreadNum = 0; @@ -517,8 +541,12 @@ public static void clearParam() { INSTANCE.minTimeRatio = 0.0; INSTANCE.maxTimeRatio = 5.0; INSTANCE.longRunningTime = 10; + INSTANCE.maxHttpConnectNumber = 50; INSTANCE.allowMultiSign = 0; INSTANCE.trxExpirationTimeInMilliseconds = 0; + INSTANCE.allowProtoFilterNum = 0; + INSTANCE.allowAccountStateRoot = 0; + INSTANCE.validContractProtoThreadNum = 1; } /** @@ -527,7 +555,8 @@ public static void clearParam() { public static void setParam(final String[] args, final String confFileName) { JCommander.newBuilder().addObject(INSTANCE).build().parse(args); if (INSTANCE.version) { - JCommander.getConsole().println(Version.getVersion() + "\n" + Version.versionName + "\n" + Version.versionCode); + JCommander.getConsole() + .println(Version.getVersion() + "\n" + Version.versionName + "\n" + Version.versionCode); exit(0); } @@ -653,6 +682,11 @@ public static void setParam(final String[] args, final String confFileName) { .map(Boolean::valueOf) .orElse(Storage.getDbVersionSyncFromConfig(config))); + INSTANCE.storage.setContractParseSwitch(Optional.ofNullable(INSTANCE.contractParseEnable) + .filter(StringUtils::isNotEmpty) + .map(Boolean::valueOf) + .orElse(Storage.getContractParseSwitchFromConfig(config))); + INSTANCE.storage.setDbDirectory(Optional.ofNullable(INSTANCE.storageDbDirectory) .filter(StringUtils::isNotEmpty) .orElse(Storage.getDbDirectoryFromConfig(config))); @@ -740,9 +774,6 @@ public static void setParam(final String[] args, final String confFileName) { INSTANCE.nodeP2pPingInterval = config.hasPath("node.p2p.pingInterval") ? config.getLong("node.p2p.pingInterval") : 0; -// -// INSTANCE.syncNodeCount = -// config.hasPath("sync.node.count") ? config.getLong("sync.node.count") : 0; INSTANCE.nodeP2pVersion = config.hasPath("node.p2p.version") ? config.getInt("node.p2p.version") : 0; @@ -780,6 +811,10 @@ public static void setParam(final String[] args, final String confFileName) { INSTANCE.blockProducedTimeOut = config.hasPath("node.blockProducedTimeOut") ? config.getInt("node.blockProducedTimeOut") : ChainConstant.BLOCK_PRODUCED_TIME_OUT; + + INSTANCE.maxHttpConnectNumber = config.hasPath("node.maxHttpConnectNumber") ? + config.getInt("node.maxHttpConnectNumber") : NodeConstant.MAX_HTTP_CONNECT_NUMBER; + if (INSTANCE.blockProducedTimeOut < 30) { INSTANCE.blockProducedTimeOut = 30; } @@ -818,6 +853,7 @@ public static void setParam(final String[] args, final String confFileName) { INSTANCE.allowMultiSign = config.hasPath("committee.allowMultiSign") ? config .getInt("committee.allowMultiSign") : 0; + INSTANCE.allowAdaptiveEnergy = config.hasPath("committee.allowAdaptiveEnergy") ? config .getInt("committee.allowAdaptiveEnergy") : 0; @@ -834,6 +870,10 @@ public static void setParam(final String[] args, final String confFileName) { config.hasPath("committee.allowTvmTransferTrc10") ? config .getInt("committee.allowTvmTransferTrc10") : 0; + INSTANCE.allowTvmConstantinople = + config.hasPath("committee.allowTvmConstantinople") ? config + .getInt("committee.allowTvmConstantinople") : 0; + INSTANCE.tcpNettyWorkThreadNum = config.hasPath("node.tcpNettyWorkThreadNum") ? config .getInt("node.tcpNettyWorkThreadNum") : 0; @@ -898,6 +938,19 @@ public static void setParam(final String[] args, final String confFileName) { INSTANCE.eventFilter = config.hasPath("event.subscribe.filter") ? getEventFilter(config) : null; + INSTANCE.allowProtoFilterNum = + config.hasPath("committee.allowProtoFilterNum") ? config + .getInt("committee.allowProtoFilterNum") : 0; + + INSTANCE.allowAccountStateRoot = + config.hasPath("committee.allowAccountStateRoot") ? config + .getInt("committee.allowAccountStateRoot") : 0; + + INSTANCE.validContractProtoThreadNum = + config.hasPath("node.validContractProto.threads") ? config + .getInt("node.validContractProto.threads") + : Runtime.getRuntime().availableProcessors(); + initBackupProperty(config); if ("ROCKSDB".equals(Args.getInstance().getStorage().getDbEngine().toUpperCase())) { initRocksDbBackupProperty(config); @@ -993,24 +1046,46 @@ private static void privateKey(final com.typesafe.config.Config config) { private static EventPluginConfig getEventPluginConfig(final com.typesafe.config.Config config) { EventPluginConfig eventPluginConfig = new EventPluginConfig(); - if (config.hasPath("event.subscribe.path")) { - String pluginPath = config.getString("event.subscribe.path"); - if (StringUtils.isNotEmpty(pluginPath)) { - eventPluginConfig.setPluginPath(pluginPath.trim()); + boolean useNativeQueue = false; + int bindPort = 0; + int sendQueueLength = 0; + if (config.hasPath("event.subscribe.native.useNativeQueue")) { + useNativeQueue = config.getBoolean("event.subscribe.native.useNativeQueue"); + + if (config.hasPath("event.subscribe.native.bindport")) { + bindPort = config.getInt("event.subscribe.native.bindport"); } - } - if (config.hasPath("event.subscribe.server")) { - String serverAddress = config.getString("event.subscribe.server"); - if (StringUtils.isNotEmpty(serverAddress)) { - eventPluginConfig.setServerAddress(serverAddress.trim()); + if (config.hasPath("event.subscribe.native.sendqueuelength")) { + sendQueueLength = config.getInt("event.subscribe.native.sendqueuelength"); } + + eventPluginConfig.setUseNativeQueue(useNativeQueue); + eventPluginConfig.setBindPort(bindPort); + eventPluginConfig.setSendQueueLength(sendQueueLength); } - if (config.hasPath("event.subscribe.dbconfig")) { - String dbConfig = config.getString("event.subscribe.dbconfig"); - if (StringUtils.isNotEmpty(dbConfig)) { - eventPluginConfig.setDbConfig(dbConfig.trim()); + // use event plugin + if (!useNativeQueue) { + if (config.hasPath("event.subscribe.path")) { + String pluginPath = config.getString("event.subscribe.path"); + if (StringUtils.isNotEmpty(pluginPath)) { + eventPluginConfig.setPluginPath(pluginPath.trim()); + } + } + + if (config.hasPath("event.subscribe.server")) { + String serverAddress = config.getString("event.subscribe.server"); + if (StringUtils.isNotEmpty(serverAddress)) { + eventPluginConfig.setServerAddress(serverAddress.trim()); + } + } + + if (config.hasPath("event.subscribe.dbconfig")) { + String dbConfig = config.getString("event.subscribe.dbconfig"); + if (StringUtils.isNotEmpty(dbConfig)) { + eventPluginConfig.setDbConfig(dbConfig.trim()); + } } } @@ -1226,7 +1301,6 @@ private static void initRocksDbBackupProperty(Config config) { .initArgs(enable, propPath, bak1path, bak2path, frequency); } - private static void initBackupProperty(Config config) { INSTANCE.backupPriority = config.hasPath("node.backup.priority") ? config.getInt("node.backup.priority") : 0; diff --git a/src/main/java/org/tron/core/config/args/Storage.java b/src/main/java/org/tron/core/config/args/Storage.java index cb7eaa2a095..5c1871178d4 100644 --- a/src/main/java/org/tron/core/config/args/Storage.java +++ b/src/main/java/org/tron/core/config/args/Storage.java @@ -60,6 +60,7 @@ public class Storage { private static final String WRITE_BUFFER_SIZE_CONFIG_KEY = "writeBufferSize"; private static final String CACHE_SIZE_CONFIG_KEY = "cacheSize"; private static final String MAX_OPEN_FILES_CONFIG_KEY = "maxOpenFiles"; + private static final String EVENT_SUBSCRIB_CONTRACT_PARSE = "event.subscribe.contractParse"; /** * Default values of directory @@ -67,6 +68,7 @@ public class Storage { private static final int DEFAULT_DB_VERSION = 2; private static final String DEFAULT_DB_ENGINE = "LEVELDB"; private static final boolean DEFAULT_DB_SYNC = false; + private static final boolean DEFAULT_EVENT_SUBSCRIB_CONTRACT_PARSE = true; private static final String DEFAULT_DB_DIRECTORY = "database"; private static final String DEFAULT_INDEX_DIRECTORY = "index"; private static final String DEFAULT_INDEX_SWTICH = "on"; @@ -113,6 +115,10 @@ public class Storage { @Setter private String indexSwitch; + @Getter + @Setter + private boolean contractParseSwitch; + @Getter @Setter private String transactionHistoreSwitch; @@ -149,6 +155,11 @@ public static Boolean getDbVersionSyncFromConfig(final Config config) { config.getBoolean(DB_SYNC_CONFIG_KEY) : DEFAULT_DB_SYNC; } + public static Boolean getContractParseSwitchFromConfig(final Config config) { + return config.hasPath(EVENT_SUBSCRIB_CONTRACT_PARSE) ? + config.getBoolean(EVENT_SUBSCRIB_CONTRACT_PARSE) : DEFAULT_EVENT_SUBSCRIB_CONTRACT_PARSE; + } + public static String getDbDirectoryFromConfig(final Config config) { return config.hasPath(DB_DIRECTORY_CONFIG_KEY) ? config.getString(DB_DIRECTORY_CONFIG_KEY) : DEFAULT_DB_DIRECTORY; diff --git a/src/main/java/org/tron/core/db/AbstractRevokingStore.java b/src/main/java/org/tron/core/db/AbstractRevokingStore.java index aa1def50de9..45872719296 100644 --- a/src/main/java/org/tron/core/db/AbstractRevokingStore.java +++ b/src/main/java/org/tron/core/db/AbstractRevokingStore.java @@ -453,9 +453,9 @@ public void close() { @Getter // only for unit test static class RevokingState { - Map oldValues = new HashMap<>(); - Set newIds = new HashSet<>(); - Map removed = new HashMap<>(); + private Map oldValues = new HashMap<>(); + private Set newIds = new HashSet<>(); + private Map removed = new HashMap<>(); } @AllArgsConstructor diff --git a/src/main/java/org/tron/core/db/AccountStore.java b/src/main/java/org/tron/core/db/AccountStore.java index 70dae1a0c25..d3174f93afd 100644 --- a/src/main/java/org/tron/core/db/AccountStore.java +++ b/src/main/java/org/tron/core/db/AccountStore.java @@ -11,6 +11,8 @@ import org.springframework.stereotype.Component; import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; +import org.tron.core.db.fast.callback.FastSyncCallBack; +import org.tron.core.db.fast.storetrie.AccountStateStoreTrie; @Slf4j(topic = "DB") @Component @@ -18,6 +20,12 @@ public class AccountStore extends TronStoreWithRevoking { private static Map assertsAddress = new HashMap<>(); // key = name , value = address + @Autowired + private FastSyncCallBack fastSyncCallBack; + + @Autowired + private AccountStateStoreTrie accountStateStoreTrie; + @Autowired private AccountStore(@Value("account") String dbName) { super(dbName); @@ -29,6 +37,13 @@ public AccountCapsule get(byte[] key) { return ArrayUtils.isEmpty(value) ? null : new AccountCapsule(value); } + + @Override + public void put(byte[] key, AccountCapsule item) { + super.put(key, item); + fastSyncCallBack.accountCallBack(key, item); + } + /** * Max TRX account. */ @@ -60,4 +75,9 @@ public static void setAccount(com.typesafe.config.Config config) { } } + @Override + public void close() { + super.close(); + accountStateStoreTrie.close(); + } } diff --git a/src/main/java/org/tron/core/db/AssetIssueStore.java b/src/main/java/org/tron/core/db/AssetIssueStore.java index b83348f9c36..b28e5c7a152 100644 --- a/src/main/java/org/tron/core/db/AssetIssueStore.java +++ b/src/main/java/org/tron/core/db/AssetIssueStore.java @@ -27,7 +27,6 @@ public AssetIssueCapsule get(byte[] key) { return super.getUnchecked(key); } - /** * get all asset issues. */ diff --git a/src/main/java/org/tron/core/db/BandwidthProcessor.java b/src/main/java/org/tron/core/db/BandwidthProcessor.java index 69a7fa39c99..35b932683fd 100644 --- a/src/main/java/org/tron/core/db/BandwidthProcessor.java +++ b/src/main/java/org/tron/core/db/BandwidthProcessor.java @@ -66,6 +66,7 @@ public void consume(TransactionCapsule trx, TransactionTrace trace) } long bytesSize; + if (dbManager.getDynamicPropertiesStore().supportVM()) { bytesSize = trx.getInstance().toBuilder().clearRet().build().getSerializedSize(); } else { diff --git a/src/main/java/org/tron/core/db/CodeStore.java b/src/main/java/org/tron/core/db/CodeStore.java index aac8ca42337..5d4929cc138 100755 --- a/src/main/java/org/tron/core/db/CodeStore.java +++ b/src/main/java/org/tron/core/db/CodeStore.java @@ -27,16 +27,6 @@ public long getTotalCodes() { return Streams.stream(revokingDB.iterator()).count(); } - private static CodeStore instance; - - public static void destory() { - instance = null; - } - - void destroy() { - instance = null; - } - public byte[] findCodeByHash(byte[] hash) { return revokingDB.getUnchecked(hash); } diff --git a/src/main/java/org/tron/core/db/ContractStore.java b/src/main/java/org/tron/core/db/ContractStore.java index 6305f63cef2..3be02d05a4c 100755 --- a/src/main/java/org/tron/core/db/ContractStore.java +++ b/src/main/java/org/tron/core/db/ContractStore.java @@ -30,16 +30,6 @@ public long getTotalContracts() { return Streams.stream(revokingDB.iterator()).count(); } - private static ContractStore instance; - - public static void destory() { - instance = null; - } - - void destroy() { - instance = null; - } - /** * find a transaction by it's id. */ diff --git a/src/main/java/org/tron/core/db/DynamicPropertiesStore.java b/src/main/java/org/tron/core/db/DynamicPropertiesStore.java index 970fd60fc3a..13a86001aab 100755 --- a/src/main/java/org/tron/core/db/DynamicPropertiesStore.java +++ b/src/main/java/org/tron/core/db/DynamicPropertiesStore.java @@ -93,7 +93,8 @@ private static class DynamicResourceProperties { private static final byte[] CREATE_NEW_ACCOUNT_FEE_IN_SYSTEM_CONTRACT = "CREATE_NEW_ACCOUNT_FEE_IN_SYSTEM_CONTRACT".getBytes(); - private static final byte[] CREATE_NEW_ACCOUNT_BANDWIDTH_RATE = "CREATE_NEW_ACCOUNT_BANDWIDTH_RATE" + private static final byte[] CREATE_NEW_ACCOUNT_BANDWIDTH_RATE = + "CREATE_NEW_ACCOUNT_BANDWIDTH_RATE" .getBytes(); private static final byte[] TRANSACTION_FEE = "TRANSACTION_FEE".getBytes(); // 1 byte @@ -161,10 +162,16 @@ private static class DynamicResourceProperties { //This value is only allowed to be 0, 1, -1 private static final byte[] ALLOW_TVM_TRANSFER_TRC10 = "ALLOW_TVM_TRANSFER_TRC10".getBytes(); + private static final byte[] ALLOW_TVM_CONSTANTINOPLE = "ALLOW_TVM_CONSTANTINOPLE".getBytes(); + + //Used only for protobuf data filter , once,value is 0,1 + private static final byte[] ALLOW_PROTO_FILTER_NUM = "ALLOW_PROTO_FILTER_NUM" + .getBytes(); private static final byte[] AVAILABLE_CONTRACT_TYPE = "AVAILABLE_CONTRACT_TYPE".getBytes(); private static final byte[] ACTIVE_DEFAULT_OPERATIONS = "ACTIVE_DEFAULT_OPERATIONS".getBytes(); - + //Used only for account state root, once,value is {0,1} allow is 1 + private static final byte[] ALLOW_ACCOUNT_STATE_ROOT = "ALLOW_ACCOUNT_STATE_ROOT".getBytes(); @Autowired private DynamicPropertiesStore(@Value("properties") String dbName) { @@ -488,6 +495,11 @@ private DynamicPropertiesStore(@Value("properties") String dbName) { this.saveAllowTvmTransferTrc10(Args.getInstance().getAllowTvmTransferTrc10()); } + try { + this.getAllowTvmConstantinople(); + } catch (IllegalArgumentException e) { + this.saveAllowTvmConstantinople(Args.getInstance().getAllowTvmConstantinople()); + } try { this.getAvailableContractType(); } catch (IllegalArgumentException e) { @@ -566,6 +578,18 @@ private DynamicPropertiesStore(@Value("properties") String dbName) { } catch (IllegalArgumentException e) { this.saveBlockEnergyUsage(0); } + + try { + this.getAllowAccountStateRoot(); + } catch (IllegalArgumentException e) { + this.saveAllowAccountStateRoot(Args.getInstance().getAllowAccountStateRoot()); + } + + try { + this.getAllowProtoFilterNum(); + } catch (IllegalArgumentException e) { + this.saveAllowProtoFilterNum(Args.getInstance().getAllowProtoFilterNum()); + } } public String intArrayToString(int[] a) { @@ -1026,7 +1050,8 @@ public long getCreateNewAccountBandwidthRate() { .map(BytesCapsule::getData) .map(ByteArray::toLong) .orElseThrow( - () -> new IllegalArgumentException("not found CREATE_NsEW_ACCOUNT_BANDWIDTH_RATE2")); + () -> new IllegalArgumentException( + "not found CREATE_NsEW_ACCOUNT_BANDWIDTH_RATE2")); } public void saveTransactionFee(long fee) { @@ -1252,6 +1277,19 @@ public long getAllowTvmTransferTrc10() { () -> new IllegalArgumentException("not found ALLOW_TVM_TRANSFER_TRC10")); } + public void saveAllowTvmConstantinople(long value) { + this.put(ALLOW_TVM_CONSTANTINOPLE, + new BytesCapsule(ByteArray.fromLong(value))); + } + + public long getAllowTvmConstantinople() { + return Optional.ofNullable(getUnchecked(ALLOW_TVM_CONSTANTINOPLE)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElseThrow( + () -> new IllegalArgumentException("not found ALLOW_TVM_CONSTANTINOPLE")); + } + public void saveAvailableContractType(byte[] value) { this.put(AVAILABLE_CONTRACT_TYPE, new BytesCapsule(value)); @@ -1265,6 +1303,26 @@ public byte[] getAvailableContractType() { } + public void addSystemContractAndSetPermission(int id){ + byte[] availableContractType = getAvailableContractType(); + availableContractType[id / 8] |= (1 << id % 8); + saveAvailableContractType(availableContractType); + + byte[] activeDefaultOperations = getActiveDefaultOperations(); + activeDefaultOperations[id / 8] |= (1 << id % 8); + saveActiveDefaultOperations(activeDefaultOperations); + } + + + public void updateDynamicStoreByConfig() { + if(Args.getInstance().getAllowTvmConstantinople() != 0) { + saveAllowTvmConstantinople(Args.getInstance().getAllowTvmConstantinople()); + addSystemContractAndSetPermission(48); + } + } + + + public void saveActiveDefaultOperations(byte[] value) { this.put(ACTIVE_DEFAULT_OPERATIONS, new BytesCapsule(value)); @@ -1277,7 +1335,6 @@ public byte[] getActiveDefaultOperations() { () -> new IllegalArgumentException("not found ACTIVE_DEFAULT_OPERATIONS")); } - public boolean supportDR() { return getAllowDelegateResource() == 1L; } @@ -1363,7 +1420,8 @@ public int[] getBlockFilledSlots() { .map(ByteArray::toStr) .map(this::stringToIntArray) .orElseThrow( - () -> new IllegalArgumentException("not found latest SOLIDIFIED_BLOCK_NUM timestamp")); + () -> new IllegalArgumentException( + "not found latest SOLIDIFIED_BLOCK_NUM timestamp")); } public int getBlockFilledSlotsNumber() { @@ -1427,7 +1485,8 @@ public long getLatestBlockHeaderTimestamp() { return Optional.ofNullable(getUnchecked(LATEST_BLOCK_HEADER_TIMESTAMP)) .map(BytesCapsule::getData) .map(ByteArray::toLong) - .orElseThrow(() -> new IllegalArgumentException("not found latest block header timestamp")); + .orElseThrow( + () -> new IllegalArgumentException("not found latest block header timestamp")); } /** @@ -1437,7 +1496,8 @@ public long getLatestBlockHeaderNumber() { return Optional.ofNullable(getUnchecked(LATEST_BLOCK_HEADER_NUMBER)) .map(BytesCapsule::getData) .map(ByteArray::toLong) - .orElseThrow(() -> new IllegalArgumentException("not found latest block header number")); + .orElseThrow( + () -> new IllegalArgumentException("not found latest block header number")); } public int getStateFlag() { @@ -1480,8 +1540,6 @@ public void saveLatestBlockHeaderNumber(long n) { public void saveLatestBlockHeaderHash(ByteString h) { logger.info("update latest block header id = {}", ByteArray.toHexString(h.toByteArray())); this.put(LATEST_BLOCK_HEADER_HASH, new BytesCapsule(h.toByteArray())); - if (revokingDB.getUnchecked(LATEST_BLOCK_HEADER_HASH).length == 32) { - } } public void saveStateFlag(int n) { @@ -1570,4 +1628,39 @@ public boolean getForked() { byte[] value = revokingDB.getUnchecked(FORK_CONTROLLER); return value == null ? Boolean.FALSE : Boolean.valueOf(new String(value)); } + + /** + * get allow protobuf number. + */ + public long getAllowProtoFilterNum() { + return Optional.ofNullable(getUnchecked(ALLOW_PROTO_FILTER_NUM)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElseThrow(() -> new IllegalArgumentException("not found allow protobuf number")); + } + + /** + * save allow protobuf number. + */ + public void saveAllowProtoFilterNum(long num) { + logger.info("update allow protobuf number = {}", num); + this.put(ALLOW_PROTO_FILTER_NUM, new BytesCapsule(ByteArray.fromLong(num))); + } + + public void saveAllowAccountStateRoot(long allowAccountStateRoot) { + this.put(ALLOW_ACCOUNT_STATE_ROOT, + new BytesCapsule(ByteArray.fromLong(allowAccountStateRoot))); + } + + public long getAllowAccountStateRoot() { + return Optional.ofNullable(getUnchecked(ALLOW_ACCOUNT_STATE_ROOT)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElseThrow( + () -> new IllegalArgumentException("not found ALLOW_ACCOUNT_STATE_ROOT")); + } + + public boolean allowAccountStateRoot() { + return getAllowAccountStateRoot() == 1; + } } diff --git a/src/main/java/org/tron/core/db/EnergyProcessor.java b/src/main/java/org/tron/core/db/EnergyProcessor.java index 2888f380890..2ce9f5703a1 100644 --- a/src/main/java/org/tron/core/db/EnergyProcessor.java +++ b/src/main/java/org/tron/core/db/EnergyProcessor.java @@ -116,11 +116,11 @@ public boolean useEnergy(AccountCapsule accountCapsule, long energy, long now) { public long calculateGlobalEnergyLimit(AccountCapsule accountCapsule) { long frozeBalance = accountCapsule.getAllFrozenBalanceForEnergy(); - if (frozeBalance < 1000_000L) { + if (frozeBalance < 1_000_000L) { return 0; } - long energyWeight = frozeBalance / 1000_000L; + long energyWeight = frozeBalance / 1_000_000L; long totalEnergyLimit = dbManager.getDynamicPropertiesStore().getTotalEnergyCurrentLimit(); long totalEnergyWeight = dbManager.getDynamicPropertiesStore().getTotalEnergyWeight(); diff --git a/src/main/java/org/tron/core/db/KhaosDatabase.java b/src/main/java/org/tron/core/db/KhaosDatabase.java index d73e95ceb89..a63056a4222 100644 --- a/src/main/java/org/tron/core/db/KhaosDatabase.java +++ b/src/main/java/org/tron/core/db/KhaosDatabase.java @@ -41,11 +41,11 @@ public KhaosBlock(BlockCapsule blk) { } @Getter - BlockCapsule blk; - Reference parent = new WeakReference<>(null); - BlockId id; - Boolean invalid; - long num; + private BlockCapsule blk; + private Reference parent = new WeakReference<>(null); + private BlockId id; + private Boolean invalid; + private long num; public KhaosBlock getParent() { return parent == null ? null : parent.get(); diff --git a/src/main/java/org/tron/core/db/Manager.java b/src/main/java/org/tron/core/db/Manager.java index c548cd47240..5608d22e1f3 100644 --- a/src/main/java/org/tron/core/db/Manager.java +++ b/src/main/java/org/tron/core/db/Manager.java @@ -31,6 +31,8 @@ import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import java.util.stream.Collectors; @@ -48,15 +50,13 @@ import org.tron.common.logsfilter.EventPluginLoader; import org.tron.common.logsfilter.FilterQuery; import org.tron.common.logsfilter.capsule.BlockLogTriggerCapsule; -import org.tron.common.logsfilter.capsule.ContractEventTriggerCapsule; -import org.tron.common.logsfilter.capsule.ContractLogTriggerCapsule; +import org.tron.common.logsfilter.capsule.ContractTriggerCapsule; import org.tron.common.logsfilter.capsule.TransactionLogTriggerCapsule; import org.tron.common.logsfilter.capsule.TriggerCapsule; -import org.tron.common.logsfilter.trigger.ContractLogTrigger; import org.tron.common.logsfilter.trigger.ContractTrigger; import org.tron.common.overlay.discover.node.Node; +import org.tron.common.overlay.message.Message; import org.tron.common.runtime.config.VMConfig; -import org.tron.common.runtime.vm.LogEventWrapper; import org.tron.common.utils.ByteArray; import org.tron.common.utils.ForkController; import org.tron.common.utils.SessionOptional; @@ -77,6 +77,8 @@ import org.tron.core.config.args.GenesisBlock; import org.tron.core.db.KhaosDatabase.KhaosBlock; import org.tron.core.db.api.AssetUpdateHelper; +import org.tron.core.db.fast.TrieService; +import org.tron.core.db.fast.callback.FastSyncCallBack; import org.tron.core.db2.core.ISession; import org.tron.core.db2.core.ITronChainBase; import org.tron.core.db2.core.SnapshotManager; @@ -220,6 +222,11 @@ public class Manager { @Getter private ForkController forkController = ForkController.instance(); + @Autowired + private FastSyncCallBack fastSyncCallBack; + + @Autowired + private TrieService trieService; private Set ownerAddressSet = new HashSet<>(); public WitnessStore getWitnessStore() { @@ -426,6 +433,9 @@ public void stopRepushTriggerThread() { @PostConstruct public void init() { + Message.setManager(this); + fastSyncCallBack.setManager(this); + trieService.setManager(this); revokingStore.disable(); revokingStore.check(); this.setWitnessController(WitnessController.createInstance(this)); @@ -459,13 +469,16 @@ public void init() { if (Args.getInstance().isNeedToUpdateAsset() && needToUpdateAsset()) { new AssetUpdateHelper(this).doWork(); } + + //for test only + dynamicPropertiesStore.updateDynamicStoreByConfig(); + initCacheTxs(); revokingStore.enable(); validateSignService = Executors .newFixedThreadPool(Args.getInstance().getValidateSignThreadNum()); Thread repushThread = new Thread(repushLoop); repushThread.start(); - // add contract event listener for subscribing if (Args.getInstance().isEventSubscribe()) { startEventSubscribing(); @@ -596,12 +609,14 @@ public void initCacheTxs() { blockCapsule.getTransactions().stream() .map(tc -> tc.getTransactionId().getBytes()) .map(bytes -> Maps.immutableEntry(bytes, Longs.toByteArray(blockNum))) - .forEach(e -> transactionCache.put(e.getKey(), new BytesCapsule(e.getValue()))); + .forEach(e -> transactionCache + .put(e.getKey(), new BytesCapsule(e.getValue()))); } catch (ItemNotFoundException | BadItemException e) { logger.info("init txs cache error."); throw new IllegalStateException("init txs cache error."); } }))); + ListenableFuture future = Futures.allAsList(futures); try { future.get(); @@ -611,6 +626,7 @@ public void initCacheTxs() { } catch (ExecutionException e) { logger.info(e.getMessage()); } + logger.info("end to init txs cache. trxids:{}, block count:{}, empty block count:{}, cost:{}", transactionCache.size(), blockCount.get(), @@ -825,7 +841,7 @@ private void applyBlock(BlockCapsule block) throws ContractValidateException, ContractExeException, ValidateSignatureException, AccountResourceInsufficientException, TransactionExpirationException, TooBigTransactionException, DupTransactionException, TaposException, ValidateScheduleException, ReceiptCheckErrException, - VMIllegalException, TooBigTransactionResultException { + VMIllegalException, TooBigTransactionResultException, BadBlockException { processBlock(block); this.blockStore.put(block.getBlockId().getBytes(), block); this.blockIndexStore.put(block.getBlockId()); @@ -842,7 +858,7 @@ private void switchFork(BlockCapsule newHead) ValidateScheduleException, AccountResourceInsufficientException, TaposException, TooBigTransactionException, TooBigTransactionResultException, DupTransactionException, TransactionExpirationException, NonCommonBlockException, ReceiptCheckErrException, - VMIllegalException { + VMIllegalException, BadBlockException { Pair, LinkedList> binaryTree; try { binaryTree = @@ -889,7 +905,8 @@ private void switchFork(BlockCapsule newHead) | TooBigTransactionException | TooBigTransactionResultException | ValidateScheduleException - | VMIllegalException e) { + | VMIllegalException + | BadBlockException e) { logger.warn(e.getMessage(), e); exception = e; throw e; @@ -1069,7 +1086,8 @@ public void updateDynamicProperties(BlockCapsule block) { if (!witnessController.getScheduledWitness(i).equals(block.getWitnessAddress())) { WitnessCapsule w = this.witnessStore - .getUnchecked(StringUtil.createDbKey(witnessController.getScheduledWitness(i))); + .getUnchecked( + StringUtil.createDbKey(witnessController.getScheduledWitness(i))); w.setTotalMissed(w.getTotalMissed() + 1); this.witnessStore.put(w.createDbKey(), w); logger.info( @@ -1204,6 +1222,7 @@ public boolean processTransaction(final TransactionCapsule trxCap, BlockCapsule VMConfig.initVmHardFork(); VMConfig.initAllowMultiSign(dynamicPropertiesStore.getAllowMultiSign()); VMConfig.initAllowTvmTransferTrc10(dynamicPropertiesStore.getAllowTvmTransferTrc10()); + VMConfig.initAllowTvmConstantinople(dynamicPropertiesStore.getAllowTvmConstantinople()); trace.init(blockCap, eventPluginLoaded); trace.checkIsConstant(); trace.exec(); @@ -1227,7 +1246,7 @@ public boolean processTransaction(final TransactionCapsule trxCap, BlockCapsule trace.finalization(); if (Objects.nonNull(blockCap) && getDynamicPropertiesStore().supportVM()) { - trxCap.setResult(trace.getRuntime()); + trxCap.setResultCode(trace.getReceipt().getResult()); } transactionStore.put(trxCap.getTransactionId().getBytes(), trxCap); @@ -1242,7 +1261,6 @@ public boolean processTransaction(final TransactionCapsule trxCap, BlockCapsule // if event subscribe is enabled, post contract triggers to queue postContractTrigger(trace, false); - // Contract contract = trxCap.getInstance().getRawData().getContract(0); if (isMultSignTransaction(trxCap.getInstance())) { ownerAddressSet.add(ByteArray.toHexString(TransactionCapsule.getOwner(contract))); @@ -1301,6 +1319,8 @@ public synchronized BlockCapsule generateBlock( blockCapsule.generatedByMyself = true; session.reset(); session.setValue(revokingStore.buildSession()); + // + fastSyncCallBack.preExecute(blockCapsule); if (needCheckWitnessPermission && !witnessService. validateWitnessPermission(witnessCapsule.getAddress())) { @@ -1327,12 +1347,14 @@ public synchronized BlockCapsule generateBlock( logger.warn("Processing transaction time exceeds the 50% producing time。"); break; } + // check the block size if ((blockCapsule.getInstance().getSerializedSize() + trx.getSerializedSize() + 3) > ChainConstant.BLOCK_SIZE) { postponedTrxCount++; continue; } + // Contract contract = trx.getInstance().getRawData().getContract(0); byte[] owner = TransactionCapsule.getOwner(contract); @@ -1349,7 +1371,9 @@ public synchronized BlockCapsule generateBlock( } // apply transaction try (ISession tmpSeesion = revokingStore.buildSession()) { + fastSyncCallBack.preExeTrans(); processTransaction(trx, blockCapsule); + fastSyncCallBack.exeTransFinish(); tmpSeesion.merge(); // push into block blockCapsule.addTransaction(trx); @@ -1389,10 +1413,11 @@ public synchronized BlockCapsule generateBlock( } catch (VMIllegalException e) { logger.warn(e.getMessage(), e); } - } + } // end of while - session.reset(); + fastSyncCallBack.executeGenerateFinish(); + session.reset(); if (postponedTrxCount > 0) { logger.info("{} transactions over the block size limit", postponedTrxCount); } @@ -1400,6 +1425,7 @@ public synchronized BlockCapsule generateBlock( logger.info( "postponedTrxCount[" + postponedTrxCount + "],TrxLeft[" + pendingTransactions.size() + "],repushTrxCount[" + repushTransactions.size() + "]"); + blockCapsule.setMerkleRoot(); blockCapsule.sign(privateKey); @@ -1456,7 +1482,6 @@ public TransactionStore getTransactionStore() { return this.transactionStore; } - public TransactionHistoryStore getTransactionHistoryStore() { return this.transactionHistoryStore; } @@ -1473,17 +1498,15 @@ public void processBlock(BlockCapsule block) throws ValidateSignatureException, ContractValidateException, ContractExeException, AccountResourceInsufficientException, TaposException, TooBigTransactionException, DupTransactionException, TransactionExpirationException, ValidateScheduleException, - ReceiptCheckErrException, VMIllegalException, TooBigTransactionResultException { + ReceiptCheckErrException, VMIllegalException, TooBigTransactionResultException, BadBlockException { // todo set revoking db max size. // checkWitness if (!witnessController.validateWitnessSchedule(block)) { throw new ValidateScheduleException("validateWitnessSchedule error"); } - //reset BlockEnergyUsage this.dynamicPropertiesStore.saveBlockEnergyUsage(0); - //parallel check sign if (!block.generatedByMyself) { try { @@ -1493,13 +1516,20 @@ public void processBlock(BlockCapsule block) Thread.currentThread().interrupt(); } } - - for (TransactionCapsule transactionCapsule : block.getTransactions()) { - transactionCapsule.setBlockNum(block.getNum()); - if (block.generatedByMyself) { - transactionCapsule.setVerified(true); + try { + fastSyncCallBack.preExecute(block); + for (TransactionCapsule transactionCapsule : block.getTransactions()) { + transactionCapsule.setBlockNum(block.getNum()); + if (block.generatedByMyself) { + transactionCapsule.setVerified(true); + } + fastSyncCallBack.preExeTrans(); + processTransaction(transactionCapsule, block); + fastSyncCallBack.exeTransFinish(); } - processTransaction(transactionCapsule, block); + fastSyncCallBack.executePushFinish(); + } finally { + fastSyncCallBack.exceptionFinish(); } boolean needMaint = needMaintenance(block.getTimeStamp()); @@ -1515,12 +1545,12 @@ public void processBlock(BlockCapsule block) energyProcessor.updateTotalEnergyAverageUsage(); energyProcessor.updateAdaptiveTotalEnergyLimit(); } - this.updateDynamicProperties(block); - this.updateSignedWitness(block); - this.updateLatestSolidifiedBlock(); - this.updateTransHashCache(block); + updateSignedWitness(block); + updateLatestSolidifiedBlock(); + updateTransHashCache(block); updateMaintenanceState(needMaint); updateRecentBlock(block); + updateDynamicProperties(block); } @@ -1544,7 +1574,8 @@ public void updateLatestSolidifiedBlock() { witnessController .getActiveWitnesses() .stream() - .map(address -> witnessController.getWitnesseByAddress(address).getLatestBlockNum()) + .map(address -> witnessController.getWitnesseByAddress(address) + .getLatestBlockNum()) .sorted() .collect(Collectors.toList()); @@ -1616,7 +1647,8 @@ public void updateSignedWitness(BlockCapsule block) { // TODO: add verification WitnessCapsule witnessCapsule = witnessStore.getUnchecked( - block.getInstance().getBlockHeader().getRawData().getWitnessAddress().toByteArray()); + block.getInstance().getBlockHeader().getRawData().getWitnessAddress() + .toByteArray()); witnessCapsule.setTotalProduced(witnessCapsule.getTotalProduced() + 1); witnessCapsule.setLatestBlockNum(block.getNum()); witnessCapsule.setLatestSlotNum(witnessController.getAbSlotAtTime(block.getTimeStamp())); @@ -1813,7 +1845,8 @@ public void rePush(TransactionCapsule tx) { try { this.pushTransaction(tx); - } catch (ValidateSignatureException | ContractValidateException | ContractExeException | AccountResourceInsufficientException | VMIllegalException e) { + } catch (ValidateSignatureException | ContractValidateException | ContractExeException + | AccountResourceInsufficientException | VMIllegalException e) { logger.debug(e.getMessage(), e); } catch (DupTransactionException e) { logger.debug("pending manager: dup trans", e); @@ -1902,27 +1935,13 @@ private void reorgContractTrigger() { private void postContractTrigger(final TransactionTrace trace, boolean remove) { if (eventPluginLoaded && (EventPluginLoader.getInstance().isContractEventTriggerEnable() - || EventPluginLoader.getInstance().isContractLogTriggerEnable() - && trace.getRuntimeResult().getTriggerList().size() > 0)) { - boolean result = false; + || EventPluginLoader.getInstance().isContractLogTriggerEnable())) { // be careful, trace.getRuntimeResult().getTriggerList() should never return null for (ContractTrigger trigger : trace.getRuntimeResult().getTriggerList()) { - if (trigger instanceof LogEventWrapper && EventPluginLoader.getInstance() - .isContractEventTriggerEnable()) { - ContractEventTriggerCapsule contractEventTriggerCapsule = new ContractEventTriggerCapsule( - (LogEventWrapper) trigger); - contractEventTriggerCapsule.getContractEventTrigger().setRemoved(remove); - contractEventTriggerCapsule.setLatestSolidifiedBlockNumber(latestSolidifiedBlockNumber); - result = triggerCapsuleQueue.offer(contractEventTriggerCapsule); - } else if (trigger instanceof ContractLogTrigger && EventPluginLoader.getInstance() - .isContractLogTriggerEnable()) { - ContractLogTriggerCapsule contractLogTriggerCapsule = new ContractLogTriggerCapsule( - (ContractLogTrigger) trigger); - contractLogTriggerCapsule.getContractLogTrigger().setRemoved(remove); - contractLogTriggerCapsule.setLatestSolidifiedBlockNumber(latestSolidifiedBlockNumber); - result = triggerCapsuleQueue.offer(contractLogTriggerCapsule); - } - if (!result) { + ContractTriggerCapsule contractEventTriggerCapsule = new ContractTriggerCapsule(trigger); + contractEventTriggerCapsule.getContractTrigger().setRemoved(remove); + contractEventTriggerCapsule.setLatestSolidifiedBlockNumber(latestSolidifiedBlockNumber); + if (!triggerCapsuleQueue.offer(contractEventTriggerCapsule)) { logger.info("too many tigger, lost contract log trigger: {}", trigger.getTransactionId()); } } diff --git a/src/main/java/org/tron/core/db/PendingManager.java b/src/main/java/org/tron/core/db/PendingManager.java index 391bb20ce1c..1e0ebcd3ff0 100644 --- a/src/main/java/org/tron/core/db/PendingManager.java +++ b/src/main/java/org/tron/core/db/PendingManager.java @@ -11,8 +11,8 @@ public class PendingManager implements AutoCloseable { @Getter - static List tmpTransactions = new ArrayList<>(); - Manager dbManager; + private List tmpTransactions = new ArrayList<>(); + private Manager dbManager; public PendingManager(Manager db) { @@ -25,7 +25,7 @@ public PendingManager(Manager db) { @Override public void close() { - for (TransactionCapsule tx : PendingManager.tmpTransactions) { + for (TransactionCapsule tx : tmpTransactions) { try { if (tx.getTrxTrace() != null && tx.getTrxTrace().getTimeResultType().equals(TimeResultType.NORMAL)) { diff --git a/src/main/java/org/tron/core/db/StorageRowStore.java b/src/main/java/org/tron/core/db/StorageRowStore.java index f8a10f28481..11e757b2b3b 100644 --- a/src/main/java/org/tron/core/db/StorageRowStore.java +++ b/src/main/java/org/tron/core/db/StorageRowStore.java @@ -10,8 +10,6 @@ @Component public class StorageRowStore extends TronStoreWithRevoking { - private static StorageRowStore instance; - @Autowired private StorageRowStore(@Value("storage-row") String dbName) { super(dbName); @@ -23,8 +21,4 @@ public StorageRowCapsule get(byte[] key) { row.setRowKey(key); return row; } - - void destory() { - instance = null; - } } diff --git a/src/main/java/org/tron/core/db/TransactionStore.java b/src/main/java/org/tron/core/db/TransactionStore.java index abdbd5e04a1..08d9abf4e3a 100644 --- a/src/main/java/org/tron/core/db/TransactionStore.java +++ b/src/main/java/org/tron/core/db/TransactionStore.java @@ -58,7 +58,7 @@ private TransactionCapsule getTransactionFromBlockStore(byte[] key, long blockNu private TransactionCapsule getTransactionFromKhaosDatabase(byte[] key, long high) { List khaosBlocks = khaosDatabase.getMiniStore().getBlockByNum(high); for (KhaosBlock bl : khaosBlocks) { - for (TransactionCapsule e : bl.blk.getTransactions()) { + for (TransactionCapsule e : bl.getBlk().getTransactions()) { if (e.getTransactionId().equals(Sha256Hash.wrap(key))) { return e; } diff --git a/src/main/java/org/tron/core/db/TransactionTrace.java b/src/main/java/org/tron/core/db/TransactionTrace.java index c34e61f675c..5e4585f82a0 100644 --- a/src/main/java/org/tron/core/db/TransactionTrace.java +++ b/src/main/java/org/tron/core/db/TransactionTrace.java @@ -8,11 +8,14 @@ import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ArrayUtils; import org.spongycastle.util.encoders.Hex; import org.springframework.util.StringUtils; import org.tron.common.runtime.Runtime; import org.tron.common.runtime.RuntimeImpl; +import org.tron.common.runtime.config.VMConfig; import org.tron.common.runtime.vm.program.InternalTransaction; +import org.tron.common.runtime.vm.program.InternalTransaction.TrxType; import org.tron.common.runtime.vm.program.Program.BadJumpDestinationException; import org.tron.common.runtime.vm.program.Program.IllegalOperationException; import org.tron.common.runtime.vm.program.Program.JVMStackOverFlowException; @@ -22,16 +25,19 @@ import org.tron.common.runtime.vm.program.Program.PrecompiledContractException; import org.tron.common.runtime.vm.program.Program.StackTooLargeException; import org.tron.common.runtime.vm.program.Program.StackTooSmallException; +import org.tron.common.runtime.vm.program.Program.TransferException; import org.tron.common.runtime.vm.program.ProgramResult; import org.tron.common.runtime.vm.program.invoke.ProgramInvokeFactoryImpl; import org.tron.common.storage.DepositImpl; import org.tron.common.utils.Sha256Hash; import org.tron.core.Constant; +import org.tron.core.Wallet; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.ContractCapsule; import org.tron.core.capsule.ReceiptCapsule; import org.tron.core.capsule.TransactionCapsule; +import org.tron.core.capsule.TransactionResultCapsule; import org.tron.core.config.args.Args; import org.tron.core.exception.BalanceInsufficientException; import org.tron.core.exception.ContractExeException; @@ -39,6 +45,7 @@ import org.tron.core.exception.ReceiptCheckErrException; import org.tron.core.exception.VMIllegalException; import org.tron.protos.Contract.TriggerSmartContract; +import org.tron.protos.Protocol.SmartContract.ABI; import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.Transaction.Contract.ContractType; import org.tron.protos.Protocol.Transaction.Result.contractResult; @@ -112,8 +119,27 @@ public void init(BlockCapsule blockCap, boolean eventPluginLoaded) { } public void checkIsConstant() throws ContractValidateException, VMIllegalException { - if (runtime.isCallConstant()) { - throw new VMIllegalException("cannot call constant method "); + if (VMConfig.allowTvmConstantinople()) { + return; + } + + TriggerSmartContract triggerContractFromTransaction = ContractCapsule + .getTriggerContractFromTransaction(this.getTrx().getInstance()); + if (TrxType.TRX_CONTRACT_CALL_TYPE == this.trxType) { + DepositImpl deposit = DepositImpl.createRoot(dbManager); + ContractCapsule contract = deposit + .getContract(triggerContractFromTransaction.getContractAddress().toByteArray()); + if (contract == null) { + logger.info("contract: {} is not in contract store", Wallet + .encode58Check(triggerContractFromTransaction.getContractAddress().toByteArray())); + throw new ContractValidateException("contract: " + Wallet + .encode58Check(triggerContractFromTransaction.getContractAddress().toByteArray()) + + " is not in contract store"); + } + ABI abi = contract.getInstance().getAbi(); + if (Wallet.isConstant(abi, triggerContractFromTransaction)) { + throw new VMIllegalException("cannot call constant method"); + } } } @@ -281,6 +307,12 @@ public void setResult() { receipt.setResult(contractResult.JVM_STACK_OVER_FLOW); return; } + if (exception instanceof TransferException) { + receipt.setResult(contractResult.TRANSFER_FAILED); + return; + } + + logger.info("uncaught exception", exception); receipt.setResult(contractResult.UNKNOWN); } diff --git a/src/main/java/org/tron/core/db/backup/BackupDbUtil.java b/src/main/java/org/tron/core/db/backup/BackupDbUtil.java index 63d89a2485c..d49e4c74509 100644 --- a/src/main/java/org/tron/core/db/backup/BackupDbUtil.java +++ b/src/main/java/org/tron/core/db/backup/BackupDbUtil.java @@ -20,7 +20,7 @@ public class BackupDbUtil { @Getter - private static String DB_BACKUP_STATE = "DB"; + private static final String DB_BACKUP_STATE = "DB"; private static final int DB_BACKUP_INDEX1 = 1; private static final int DB_BACKUP_INDEX2 = 2; @@ -29,9 +29,9 @@ public class BackupDbUtil { public enum State { BAKINGONE(1), BAKEDONE(11), BAKINGTWO(2), BAKEDTWO(22); - public int status; + private int status; - private State(int status) { + State(int status) { this.status = status; } diff --git a/src/main/java/org/tron/core/db/backup/BackupRocksDBAspect.java b/src/main/java/org/tron/core/db/backup/BackupRocksDBAspect.java index 0e33198bd47..3bdab8550fb 100644 --- a/src/main/java/org/tron/core/db/backup/BackupRocksDBAspect.java +++ b/src/main/java/org/tron/core/db/backup/BackupRocksDBAspect.java @@ -14,7 +14,6 @@ @Slf4j @Aspect public class BackupRocksDBAspect { - @Autowired private BackupDbUtil util; @@ -30,7 +29,7 @@ public void pointPushBlock(BlockCapsule block) { @Before("pointPushBlock(block)") public void backupDb(BlockCapsule block) { //SR-Master Node do not backup db; - if (Args.getInstance().isWitness() && !(backupManager.getStatus() == BackupStatusEnum.SLAVER)) { + if (Args.getInstance().isWitness() && backupManager.getStatus() != BackupStatusEnum.SLAVER) { return; } @@ -39,7 +38,7 @@ public void backupDb(BlockCapsule block) { try { util.doBackup(block); } catch (Exception e) { - logger.error("backup db failure: {}", e); + logger.error("backup db failure:", e); } } } diff --git a/src/main/java/org/tron/core/db/fast/AccountStateEntity.java b/src/main/java/org/tron/core/db/fast/AccountStateEntity.java new file mode 100644 index 00000000000..6055c05b388 --- /dev/null +++ b/src/main/java/org/tron/core/db/fast/AccountStateEntity.java @@ -0,0 +1,51 @@ +package org.tron.core.db.fast; + +import lombok.extern.slf4j.Slf4j; +import org.tron.core.Wallet; +import org.tron.protos.Protocol.Account; + +@Slf4j(topic = "AccountState") +public class AccountStateEntity { + + private Account account; + + public AccountStateEntity() { + } + + public AccountStateEntity(Account account) { + Account.Builder builder = Account.newBuilder(); + builder.setAddress(account.getAddress()); + builder.setBalance(account.getBalance()); + //builder.putAllAssetV2(account.getAssetV2Map()); + builder.setAllowance(account.getAllowance()); + this.account = builder.build(); + } + + public Account getAccount() { + return account; + } + + public AccountStateEntity setAccount(Account account) { + this.account = account; + return this; + } + + public byte[] toByteArrays() { + return account.toByteArray(); + } + + public static AccountStateEntity parse(byte[] data) { + try { + return new AccountStateEntity().setAccount(Account.parseFrom(data)); + } catch (Exception e) { + logger.error("parse to AccountStateEntity error! reason: {}", e.getMessage()); + } + return null; + } + + @Override + public String toString() { + return "address:" + Wallet.encode58Check(account.getAddress().toByteArray()) + "; " + account + .toString(); + } +} diff --git a/src/main/java/org/tron/core/db/fast/TrieService.java b/src/main/java/org/tron/core/db/fast/TrieService.java new file mode 100644 index 00000000000..bb4c3edc60e --- /dev/null +++ b/src/main/java/org/tron/core/db/fast/TrieService.java @@ -0,0 +1,50 @@ +package org.tron.core.db.fast; + +import com.google.protobuf.ByteString; +import com.google.protobuf.Internal; +import java.util.Arrays; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.tron.common.crypto.Hash; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.db.Manager; +import org.tron.core.db.fast.storetrie.AccountStateStoreTrie; + +@Slf4j(topic = "AccountState") +@Component +public class TrieService { + + @Setter + private Manager manager; + + @Setter + private AccountStateStoreTrie accountStateStoreTrie; + + public byte[] getFullAccountStateRootHash() { + long latestNumber = manager.getDynamicPropertiesStore().getLatestBlockHeaderNumber(); + return getAccountStateRootHash(latestNumber); + } + + public byte[] getSolidityAccountStateRootHash() { + long latestSolidityNumber = manager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum(); + return getAccountStateRootHash(latestSolidityNumber); + } + + private byte[] getAccountStateRootHash(long blockNumber) { + long latestNumber = blockNumber; + byte[] rootHash = null; + try { + BlockCapsule blockCapsule = manager.getBlockByNum(latestNumber); + ByteString value = blockCapsule.getInstance().getBlockHeader().getRawData() + .getAccountStateRoot(); + rootHash = value == null ? null : value.toByteArray(); + if (Arrays.equals(rootHash, Internal.EMPTY_BYTE_ARRAY)) { + rootHash = Hash.EMPTY_TRIE_HASH; + } + } catch (Exception e) { + logger.error("Get the {} block error.", latestNumber, e); + } + return rootHash; + } +} diff --git a/src/main/java/org/tron/core/db/fast/callback/FastSyncCallBack.java b/src/main/java/org/tron/core/db/fast/callback/FastSyncCallBack.java new file mode 100644 index 00000000000..577f1b89f4a --- /dev/null +++ b/src/main/java/org/tron/core/db/fast/callback/FastSyncCallBack.java @@ -0,0 +1,187 @@ +package org.tron.core.db.fast.callback; + +import com.google.protobuf.ByteString; +import com.google.protobuf.Internal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ArrayUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.common.crypto.Hash; +import org.tron.common.utils.ByteUtil; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.BlockCapsule; +import org.tron.core.capsule.utils.RLP; +import org.tron.core.db.Manager; +import org.tron.core.db.fast.AccountStateEntity; +import org.tron.core.db.fast.storetrie.AccountStateStoreTrie; +import org.tron.core.exception.BadBlockException; +import org.tron.core.trie.TrieImpl; +import org.tron.core.trie.TrieImpl.Node; +import org.tron.core.trie.TrieImpl.ScanAction; + +@Slf4j(topic = "AccountState") +@Component +public class FastSyncCallBack { + + private BlockCapsule blockCapsule; + private volatile boolean execute = false; + private volatile boolean allowGenerateRoot = false; + private TrieImpl trie; + + @Setter + private Manager manager; + + @Autowired + private AccountStateStoreTrie db; + + private List trieEntryList = new ArrayList<>(); + + private static class TrieEntry { + + private byte[] key; + private byte[] data; + + public byte[] getKey() { + return key; + } + + public TrieEntry setKey(byte[] key) { + this.key = key; + return this; + } + + public byte[] getData() { + return data; + } + + public TrieEntry setData(byte[] data) { + this.data = data; + return this; + } + + public static TrieEntry build(byte[] key, byte[] data) { + TrieEntry trieEntry = new TrieEntry(); + return trieEntry.setKey(key).setData(data); + } + } + + public void accountCallBack(byte[] key, AccountCapsule item) { + if (!exe()) { + return; + } + if (item == null) { + return; + } + trieEntryList + .add(TrieEntry.build(key, new AccountStateEntity(item.getInstance()).toByteArrays())); + } + + public void preExeTrans() { + trieEntryList.clear(); + } + + public void exeTransFinish() { + for (TrieEntry trieEntry : trieEntryList) { + trie.put(RLP.encodeElement(trieEntry.getKey()), trieEntry.getData()); + } + trieEntryList.clear(); + } + + public void deleteAccount(byte[] key) { + if (!exe()) { + return; + } + trie.delete(RLP.encodeElement(key)); + } + + public void preExecute(BlockCapsule blockCapsule) { + this.blockCapsule = blockCapsule; + this.execute = true; + this.allowGenerateRoot = manager.getDynamicPropertiesStore().allowAccountStateRoot(); + if (!exe()) { + return; + } + byte[] rootHash = null; + try { + BlockCapsule parentBlockCapsule = manager.getBlockById(blockCapsule.getParentBlockId()); + rootHash = parentBlockCapsule.getInstance().getBlockHeader().getRawData() + .getAccountStateRoot().toByteArray(); + } catch (Exception e) { + logger.error("", e); + } + if (Arrays.equals(Internal.EMPTY_BYTE_ARRAY, rootHash)) { + rootHash = Hash.EMPTY_TRIE_HASH; + } + trie = new TrieImpl(db, rootHash); + } + + public void executePushFinish() throws BadBlockException { + if (!exe()) { + return; + } + ByteString oldRoot = blockCapsule.getInstance().getBlockHeader().getRawData() + .getAccountStateRoot(); + execute = false; + // + byte[] newRoot = trie.getRootHash(); + if (ArrayUtils.isEmpty(newRoot)) { + newRoot = Hash.EMPTY_TRIE_HASH; + } + if (!oldRoot.isEmpty() && !Arrays.equals(oldRoot.toByteArray(), newRoot)) { + logger.error("the accountStateRoot hash is error. {}, oldRoot: {}, newRoot: {}", + blockCapsule.getBlockId().getString(), ByteUtil.toHexString(oldRoot.toByteArray()), + ByteUtil.toHexString(newRoot)); + printErrorLog(trie); + throw new BadBlockException("the accountStateRoot hash is error"); + } + } + + public void executeGenerateFinish() { + if (!exe()) { + return; + } + // + byte[] newRoot = trie.getRootHash(); + if (ArrayUtils.isEmpty(newRoot)) { + newRoot = Hash.EMPTY_TRIE_HASH; + } + blockCapsule.setAccountStateRoot(newRoot); + execute = false; + } + + public void exceptionFinish() { + execute = false; + } + + private boolean exe() { + if (!execute || !allowGenerateRoot) { + //Agreement same block high to generate account state root + execute = false; + return false; + } + return true; + } + + private void printErrorLog(TrieImpl trie) { + trie.scanTree(new ScanAction() { + @Override + public void doOnNode(byte[] hash, Node node) { + + } + + @Override + public void doOnValue(byte[] nodeHash, Node node, byte[] key, byte[] value) { + try { + logger.info("account info : {}", AccountStateEntity.parse(value)); + } catch (Exception e) { + logger.error("", e); + } + } + }); + } + +} diff --git a/src/main/java/org/tron/core/db/fast/storetrie/AccountStateStoreTrie.java b/src/main/java/org/tron/core/db/fast/storetrie/AccountStateStoreTrie.java new file mode 100644 index 00000000000..0c85c3ef34e --- /dev/null +++ b/src/main/java/org/tron/core/db/fast/storetrie/AccountStateStoreTrie.java @@ -0,0 +1,68 @@ +package org.tron.core.db.fast.storetrie; + +import javax.annotation.PostConstruct; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ArrayUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.tron.core.capsule.BytesCapsule; +import org.tron.core.capsule.utils.RLP; +import org.tron.core.db.TronStoreWithRevoking; +import org.tron.core.db.fast.AccountStateEntity; +import org.tron.core.db.fast.TrieService; +import org.tron.core.db2.common.DB; +import org.tron.core.trie.TrieImpl; + +@Slf4j(topic = "AccountState") +@Component +public class AccountStateStoreTrie extends TronStoreWithRevoking implements + DB { + + @Autowired + private TrieService trieService; + + @Autowired + private AccountStateStoreTrie(@Value("accountTrie") String dbName) { + super(dbName); + } + + @PostConstruct + public void init() { + trieService.setAccountStateStoreTrie(this); + } + + public AccountStateEntity getAccount(byte[] key) { + return getAccount(key, trieService.getFullAccountStateRootHash()); + } + + public AccountStateEntity getSolidityAccount(byte[] key) { + return getAccount(key, trieService.getSolidityAccountStateRootHash()); + } + + public AccountStateEntity getAccount(byte[] key, byte[] rootHash) { + TrieImpl trie = new TrieImpl(this, rootHash); + byte[] value = trie.get(RLP.encodeElement(key)); + return ArrayUtils.isEmpty(value) ? null : AccountStateEntity.parse(value); + } + + @Override + public boolean isEmpty() { + return super.size() <= 0; + } + + @Override + public void remove(byte[] bytes) { + super.delete(bytes); + } + + @Override + public BytesCapsule get(byte[] key) { + return super.getUnchecked(key); + } + + @Override + public void put(byte[] key, BytesCapsule item) { + super.put(key, item); + } +} diff --git a/src/main/java/org/tron/core/db2/common/ConcurrentHashDB.java b/src/main/java/org/tron/core/db2/common/ConcurrentHashDB.java new file mode 100644 index 00000000000..c7f4ff704f7 --- /dev/null +++ b/src/main/java/org/tron/core/db2/common/ConcurrentHashDB.java @@ -0,0 +1,43 @@ +package org.tron.core.db2.common; + +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; +import org.tron.core.capsule.BytesCapsule; + +public class ConcurrentHashDB implements DB { + + private Map db = new ConcurrentHashMap<>(); + + + @Override + public BytesCapsule get(byte[] bytes) { + return db.get(Key.of(bytes)); + } + + @Override + public void put(byte[] bytes, BytesCapsule bytes2) { + db.put(Key.of(bytes), bytes2); + } + + @Override + public long size() { + return db.size(); + } + + @Override + public boolean isEmpty() { + return db.isEmpty(); + } + + @Override + public void remove(byte[] bytes) { + db.remove(Key.of(bytes)); + } + + @Override + public Iterator> iterator() { + return null; + } +} diff --git a/src/main/java/org/tron/core/db2/common/IRevokingDB.java b/src/main/java/org/tron/core/db2/common/IRevokingDB.java index 1059f7c0daa..7d52c37b288 100644 --- a/src/main/java/org/tron/core/db2/common/IRevokingDB.java +++ b/src/main/java/org/tron/core/db2/common/IRevokingDB.java @@ -2,6 +2,7 @@ import java.util.Map; import java.util.Set; +import org.tron.core.db.common.WrappedByteArray; import org.tron.core.exception.ItemNotFoundException; public interface IRevokingDB extends Iterable> { @@ -27,5 +28,9 @@ public interface IRevokingDB extends Iterable> { // for blockstore Set getValuesNext(byte[] key, long limit); + + // for deferTransaction + Set getValuesPrevious(byte[] key, long limit); + Map getAllValues(); } diff --git a/src/main/java/org/tron/core/db2/core/RevokingDBWithCachingNewValue.java b/src/main/java/org/tron/core/db2/core/RevokingDBWithCachingNewValue.java index 0f28024ab26..eac4ac386b5 100644 --- a/src/main/java/org/tron/core/db2/core/RevokingDBWithCachingNewValue.java +++ b/src/main/java/org/tron/core/db2/core/RevokingDBWithCachingNewValue.java @@ -6,6 +6,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; @@ -154,23 +155,25 @@ private Set getValuesNext(Snapshot head, byte[] key, long limit) { ((SnapshotImpl) head).collect(collection); } - Map levelDBMap = new HashMap<>(); + Map levelDbMap = new HashMap<>(); if (((SnapshotRoot) head.getRoot()).db.getClass() == LevelDB.class) { ((LevelDB) ((SnapshotRoot) head.getRoot()).db).getDb().getNext(key, limit).entrySet().stream() .map(e -> Maps - .immutableEntry(WrappedByteArray.of(e.getKey()), WrappedByteArray.of(e.getValue()))) - .forEach(e -> levelDBMap.put(e.getKey(), e.getValue())); + .immutableEntry(WrappedByteArray.of(e.getKey()), + WrappedByteArray.of(e.getValue()))) + .forEach(e -> levelDbMap.put(e.getKey(), e.getValue())); } else if (((SnapshotRoot) head.getRoot()).db.getClass() == RocksDB.class) { ((RocksDB) ((SnapshotRoot) head.getRoot()).db).getDb().getNext(key, limit).entrySet().stream() .map(e -> Maps - .immutableEntry(WrappedByteArray.of(e.getKey()), WrappedByteArray.of(e.getValue()))) - .forEach(e -> levelDBMap.put(e.getKey(), e.getValue())); + .immutableEntry(WrappedByteArray.of(e.getKey()), + WrappedByteArray.of(e.getValue()))) + .forEach(e -> levelDbMap.put(e.getKey(), e.getValue())); } - levelDBMap.putAll(collection); + levelDbMap.putAll(collection); - return levelDBMap.entrySet().stream() + return levelDbMap.entrySet().stream() .sorted((e1, e2) -> ByteUtil.compare(e1.getKey().getBytes(), e2.getKey().getBytes())) .filter(e -> ByteUtil.greaterOrEquals(e.getKey().getBytes(), key)) .limit(limit) @@ -183,4 +186,50 @@ private Set getValuesNext(Snapshot head, byte[] key, long limit) { public Set getValuesNext(byte[] key, long limit) { return getValuesNext(head(), key, limit); } + + @Override + public Set getValuesPrevious(byte[] key, long limit) { + Map collection = new HashMap<>(); + if (head.getPrevious() != null) { + ((SnapshotImpl) head).collect(collection); + } + int precision = Long.SIZE / Byte.SIZE; + Set result = new HashSet<>(); + for (WrappedByteArray p : collection.keySet()) { + if (ByteUtil.lessOrEquals(ByteUtil.parseBytes(p.getBytes(), 0, precision), key) + && limit > 0) { + result.add(collection.get(p).getBytes()); + limit--; + } + } + if (limit <= 0) { + return result; + } + List list = null; + if (((SnapshotRoot) head.getRoot()).db.getClass() == LevelDB.class) { + list = ((LevelDB) ((SnapshotRoot) head.getRoot()).db).getDb() + .getPrevious(key, limit, precision).values().stream() + .collect(Collectors.toList()); + } else if (((SnapshotRoot) head.getRoot()).db.getClass() == RocksDB.class) { + list = ((RocksDB) ((SnapshotRoot) head.getRoot()).db).getDb() + .getPrevious(key, limit, precision).values().stream() + .collect(Collectors.toList()); + } + result.addAll(list); + return result.stream().limit(limit).collect(Collectors.toSet()); + } + + public Map getAllValues() { + Map collection = new HashMap<>(); + if (head.getPrevious() != null) { + ((SnapshotImpl) head).collect(collection); + } + Map levelDBMap = new HashMap<>(); + ((LevelDB) ((SnapshotRoot) head.getRoot()).db).getDb().getAll().entrySet().stream() + .map(e -> Maps.immutableEntry(WrappedByteArray.of(e.getKey()), + WrappedByteArray.of(e.getValue()))) + .forEach(e -> levelDBMap.put(e.getKey(), e.getValue())); + levelDBMap.putAll(collection); + return levelDBMap; + } } diff --git a/src/main/java/org/tron/core/db2/core/RevokingDBWithCachingOldValue.java b/src/main/java/org/tron/core/db2/core/RevokingDBWithCachingOldValue.java index 459d7b17584..53b998843e5 100644 --- a/src/main/java/org/tron/core/db2/core/RevokingDBWithCachingOldValue.java +++ b/src/main/java/org/tron/core/db2/core/RevokingDBWithCachingOldValue.java @@ -1,15 +1,18 @@ package org.tron.core.db2.core; +import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.stream.Collectors; import lombok.Getter; import org.apache.commons.lang3.ArrayUtils; import org.tron.common.storage.leveldb.LevelDbDataSourceImpl; import org.tron.core.config.args.Args; import org.tron.core.db.AbstractRevokingStore; import org.tron.core.db.RevokingStore; +import org.tron.core.db.common.WrappedByteArray; import org.tron.core.db2.common.IRevokingDB; import org.tron.core.exception.ItemNotFoundException; @@ -130,4 +133,18 @@ public Set getlatestValues(long limit) { public Set getValuesNext(byte[] key, long limit) { return dbSource.getValuesNext(key, limit); } + + @Override + public Set getValuesPrevious(byte[] key, long limit) { + return dbSource.getPrevious(key, limit, Long.SIZE / Byte.SIZE).values().stream() + .collect(Collectors.toSet()); + } + + public Map getAllValues() { + Map result = new HashMap<>(); + dbSource.getAll().forEach((key, value) -> { + result.put(WrappedByteArray.of(key), WrappedByteArray.of(value)); + }); + return result; + } } diff --git a/src/main/java/org/tron/core/exception/P2pException.java b/src/main/java/org/tron/core/exception/P2pException.java index ae592ac67f9..8931af3a179 100644 --- a/src/main/java/org/tron/core/exception/P2pException.java +++ b/src/main/java/org/tron/core/exception/P2pException.java @@ -37,6 +37,7 @@ public enum TypeEnum { BAD_TRX(11, "bad trx"), TRX_EXE_FAILED(12, "trx exe failed"), DB_ITEM_NOT_FOUND(13, "DB item not found"), + PROTOBUF_ERROR(14, "protobuf inconsistent"), DEFAULT(100, "default exception"); diff --git a/src/main/java/org/tron/core/exception/RevokingStoreIllegalStateException.java b/src/main/java/org/tron/core/exception/RevokingStoreIllegalStateException.java index ad3724fc4b8..5718e86d4a5 100755 --- a/src/main/java/org/tron/core/exception/RevokingStoreIllegalStateException.java +++ b/src/main/java/org/tron/core/exception/RevokingStoreIllegalStateException.java @@ -50,5 +50,5 @@ public RevokingStoreIllegalStateException(Throwable cause) { super("", cause); } - static final long serialVersionUID = -1848914673093119416L; + public static final long serialVersionUID = -1848914673093119416L; } diff --git a/src/main/java/org/tron/core/net/TronNetDelegate.java b/src/main/java/org/tron/core/net/TronNetDelegate.java index 113cc822f65..969c42d7123 100644 --- a/src/main/java/org/tron/core/net/TronNetDelegate.java +++ b/src/main/java/org/tron/core/net/TronNetDelegate.java @@ -46,7 +46,7 @@ import org.tron.core.net.peer.PeerConnection; import org.tron.protos.Protocol.Inventory.InventoryType; -@Slf4j +@Slf4j(topic = "net") @Component public class TronNetDelegate { @@ -155,7 +155,7 @@ public Message getData(Sha256Hash hash, InventoryType type) throws P2pException case TRX: TransactionCapsule tx = dbManager.getTransactionStore().get(hash.getBytes()); if (tx != null) { - return new TransactionMessage(tx.getData()); + return new TransactionMessage(tx.getInstance()); } throw new StoreException(); default: diff --git a/src/main/java/org/tron/core/net/TronNetService.java b/src/main/java/org/tron/core/net/TronNetService.java index a8a6ad46dfa..0fa16eb7f50 100644 --- a/src/main/java/org/tron/core/net/TronNetService.java +++ b/src/main/java/org/tron/core/net/TronNetService.java @@ -20,7 +20,7 @@ import org.tron.core.net.service.SyncService; import org.tron.protos.Protocol.ReasonCode; -@Slf4j +@Slf4j(topic = "net") @Component public class TronNetService { @@ -129,7 +129,7 @@ private void processException(PeerConnection peer, TronMessage msg, Exception ex case UNLINK_BLOCK: code = ReasonCode.UNLINKABLE; break; - case DEFAULT: + default: code = ReasonCode.UNKNOWN; break; } diff --git a/src/main/java/org/tron/core/net/message/BlockInventoryMessage.java b/src/main/java/org/tron/core/net/message/BlockInventoryMessage.java index 629f350f5c1..7d7b8220722 100644 --- a/src/main/java/org/tron/core/net/message/BlockInventoryMessage.java +++ b/src/main/java/org/tron/core/net/message/BlockInventoryMessage.java @@ -3,7 +3,6 @@ import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; -import org.apache.commons.collections4.CollectionUtils; import org.tron.core.capsule.BlockCapsule.BlockId; import org.tron.protos.Protocol; import org.tron.protos.Protocol.BlockInventory; @@ -13,8 +12,8 @@ public class BlockInventoryMessage extends TronMessage { protected BlockInventory blockInventory; public BlockInventoryMessage(byte[] data) throws Exception { + super(data); this.type = MessageTypes.BLOCK_INVENTORY.asByte(); - this.data = data; this.blockInventory = Protocol.BlockInventory.parseFrom(data); } diff --git a/src/main/java/org/tron/core/net/message/BlockMessage.java b/src/main/java/org/tron/core/net/message/BlockMessage.java index b66c7735021..1b4c42e8060 100644 --- a/src/main/java/org/tron/core/net/message/BlockMessage.java +++ b/src/main/java/org/tron/core/net/message/BlockMessage.java @@ -1,18 +1,23 @@ package org.tron.core.net.message; +import org.tron.common.overlay.message.Message; import org.tron.common.utils.Sha256Hash; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.BlockCapsule.BlockId; -import org.tron.core.exception.BadItemException; +import org.tron.core.capsule.TransactionCapsule; public class BlockMessage extends TronMessage { private BlockCapsule block; - public BlockMessage(byte[] data) throws BadItemException { + public BlockMessage(byte[] data) throws Exception { + super(data); this.type = MessageTypes.BLOCK.asByte(); - this.data = data; - this.block = new BlockCapsule(data); + this.block = new BlockCapsule(getCodedInputStream(data)); + if (Message.isFilter()) { + Message.compareBytes(data, block.getInstance().toByteArray()); + TransactionCapsule.validContractProto(block.getInstance().getTransactionsList()); + } } public BlockMessage(BlockCapsule block) { diff --git a/src/main/java/org/tron/core/net/message/BlocksMessage.java b/src/main/java/org/tron/core/net/message/BlocksMessage.java index dedd56fd80e..7c7f602adf7 100644 --- a/src/main/java/org/tron/core/net/message/BlocksMessage.java +++ b/src/main/java/org/tron/core/net/message/BlocksMessage.java @@ -2,6 +2,8 @@ import java.util.List; import org.apache.commons.collections4.CollectionUtils; +import org.tron.core.capsule.TransactionCapsule; +import org.tron.protos.Protocol; import org.tron.protos.Protocol.Block; import org.tron.protos.Protocol.Items; @@ -10,12 +12,18 @@ public class BlocksMessage extends TronMessage { private List blocks; public BlocksMessage(byte[] data) throws Exception { + super(data); this.type = MessageTypes.BLOCKS.asByte(); - this.data = data; - Items items = Items.parseFrom(data); + Items items = Items.parseFrom(getCodedInputStream(data)); if (items.getType() == Items.ItemType.BLOCK) { blocks = items.getBlocksList(); } + if (isFilter() && CollectionUtils.isNotEmpty(blocks)) { + compareBytes(data, items.toByteArray()); + for (Block block : blocks) { + TransactionCapsule.validContractProto(block.getTransactionsList()); + } + } } public List getBlocks() { diff --git a/src/main/java/org/tron/core/net/message/ChainInventoryMessage.java b/src/main/java/org/tron/core/net/message/ChainInventoryMessage.java index 8368c3e192e..5b0a0398778 100644 --- a/src/main/java/org/tron/core/net/message/ChainInventoryMessage.java +++ b/src/main/java/org/tron/core/net/message/ChainInventoryMessage.java @@ -14,8 +14,8 @@ public class ChainInventoryMessage extends TronMessage { protected ChainInventory chainInventory; public ChainInventoryMessage(byte[] data) throws Exception { + super(data); this.type = MessageTypes.BLOCK_CHAIN_INVENTORY.asByte(); - this.data = data; chainInventory = Protocol.ChainInventory.parseFrom(data); } diff --git a/src/main/java/org/tron/core/net/message/InventoryMessage.java b/src/main/java/org/tron/core/net/message/InventoryMessage.java index 1de78ca9a0e..701270a6626 100644 --- a/src/main/java/org/tron/core/net/message/InventoryMessage.java +++ b/src/main/java/org/tron/core/net/message/InventoryMessage.java @@ -15,8 +15,8 @@ public class InventoryMessage extends TronMessage { protected Inventory inv; public InventoryMessage(byte[] data) throws Exception { + super(data); this.type = MessageTypes.INVENTORY.asByte(); - this.data = data; this.inv = Protocol.Inventory.parseFrom(data); } diff --git a/src/main/java/org/tron/core/net/message/SyncBlockChainMessage.java b/src/main/java/org/tron/core/net/message/SyncBlockChainMessage.java index dd5f1028861..3163660ecb2 100644 --- a/src/main/java/org/tron/core/net/message/SyncBlockChainMessage.java +++ b/src/main/java/org/tron/core/net/message/SyncBlockChainMessage.java @@ -1,7 +1,6 @@ package org.tron.core.net.message; import java.util.List; -import org.apache.commons.collections4.CollectionUtils; import org.tron.core.capsule.BlockCapsule.BlockId; import org.tron.protos.Protocol.BlockInventory.Type; diff --git a/src/main/java/org/tron/core/net/message/TransactionMessage.java b/src/main/java/org/tron/core/net/message/TransactionMessage.java index 5757df59b0d..dfd46a918a2 100644 --- a/src/main/java/org/tron/core/net/message/TransactionMessage.java +++ b/src/main/java/org/tron/core/net/message/TransactionMessage.java @@ -1,18 +1,25 @@ package org.tron.core.net.message; +import org.tron.common.overlay.message.Message; import org.tron.common.utils.Sha256Hash; import org.tron.core.capsule.TransactionCapsule; import org.tron.core.exception.BadItemException; +import org.tron.core.exception.P2pException; import org.tron.protos.Protocol.Transaction; public class TransactionMessage extends TronMessage { private TransactionCapsule transactionCapsule; - public TransactionMessage(byte[] data) throws BadItemException { - this.transactionCapsule = new TransactionCapsule(data); - this.data = data; + public TransactionMessage(byte[] data) throws Exception { + super(data); + this.transactionCapsule = new TransactionCapsule(getCodedInputStream(data)); this.type = MessageTypes.TRX.asByte(); + if (Message.isFilter()) { + compareBytes(data, transactionCapsule.getInstance().toByteArray()); + transactionCapsule + .validContractProto(transactionCapsule.getInstance().getRawData().getContract(0)); + } } public TransactionMessage(Transaction trx) { diff --git a/src/main/java/org/tron/core/net/message/TransactionsMessage.java b/src/main/java/org/tron/core/net/message/TransactionsMessage.java index 39373e15528..72110041e87 100644 --- a/src/main/java/org/tron/core/net/message/TransactionsMessage.java +++ b/src/main/java/org/tron/core/net/message/TransactionsMessage.java @@ -1,8 +1,7 @@ package org.tron.core.net.message; import java.util.List; - -import org.tron.core.exception.P2pException; +import org.tron.core.capsule.TransactionCapsule; import org.tron.protos.Protocol; import org.tron.protos.Protocol.Transaction; @@ -19,9 +18,13 @@ public TransactionsMessage(List trxs) { } public TransactionsMessage(byte[] data) throws Exception { + super(data); this.type = MessageTypes.TRXS.asByte(); - this.data = data; - this.transactions = Protocol.Transactions.parseFrom(data); + this.transactions = Protocol.Transactions.parseFrom(getCodedInputStream(data)); + if (isFilter()) { + compareBytes(data, transactions.toByteArray()); + TransactionCapsule.validContractProto(transactions.getTransactionsList()); + } } public Protocol.Transactions getTransactions() { diff --git a/src/main/java/org/tron/core/net/message/TronMessageFactory.java b/src/main/java/org/tron/core/net/message/TronMessageFactory.java index be4eedd8343..37ad91fd664 100644 --- a/src/main/java/org/tron/core/net/message/TronMessageFactory.java +++ b/src/main/java/org/tron/core/net/message/TronMessageFactory.java @@ -19,7 +19,7 @@ public TronMessage create(byte[] data) throws Exception { throw e; } catch (final Exception e) { throw new P2pException(P2pException.TypeEnum.PARSE_MESSAGE_FAILED, - "type=" + data[0] + ", len=" + data.length); + "type=" + data[0] + ", len=" + data.length + ", error msg: " + e.getMessage()); } } diff --git a/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java b/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java index 7a038acd948..943874047bc 100644 --- a/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java +++ b/src/main/java/org/tron/core/net/messagehandler/BlockMsgHandler.java @@ -21,7 +21,7 @@ import org.tron.core.services.WitnessProductBlockService; import org.tron.protos.Protocol.Inventory.InventoryType; -@Slf4j +@Slf4j(topic = "net") @Component public class BlockMsgHandler implements TronMsgHandler { @@ -54,6 +54,8 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep peer.getSyncBlockRequested().remove(blockId); syncService.processBlock(peer, blockMessage); } else { + logger.info("Receive block {} from {}, cost {}ms", blockId.getString(), peer.getInetAddress(), + System.currentTimeMillis() - peer.getAdvInvRequest().get(item)); peer.getAdvInvRequest().remove(item); processBlock(peer, blockMessage.getBlockCapsule()); } diff --git a/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java b/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java index 74737d79de1..c54a66f477e 100644 --- a/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java +++ b/src/main/java/org/tron/core/net/messagehandler/ChainInventoryMsgHandler.java @@ -20,7 +20,7 @@ import org.tron.core.net.peer.PeerConnection; import org.tron.core.net.service.SyncService; -@Slf4j +@Slf4j(topic = "net") @Component public class ChainInventoryMsgHandler implements TronMsgHandler { @@ -64,13 +64,14 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep while (!peer.getSyncBlockToFetch().isEmpty() && tronNetDelegate .containBlock(peer.getSyncBlockToFetch().peek())) { BlockId blockId = peer.getSyncBlockToFetch().pop(); + peer.setBlockBothHave(blockId); logger.info("Block {} from {} is processed", blockId.getString(), peer.getNode().getHost()); } } -// -// if (chainInventoryMessage.getRemainNum() == 0 && peer.getSyncBlockToFetch().isEmpty()) { -// peer.setNeedSyncFromPeer(false); -// } + + //if (chainInventoryMessage.getRemainNum() == 0 && peer.getSyncBlockToFetch().isEmpty()) { + // peer.setNeedSyncFromPeer(false); + //} if ((chainInventoryMessage.getRemainNum() == 0 && !peer.getSyncBlockToFetch().isEmpty()) || (chainInventoryMessage.getRemainNum() != 0 diff --git a/src/main/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandler.java b/src/main/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandler.java index 422ca9d58cd..b0534349eed 100644 --- a/src/main/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandler.java +++ b/src/main/java/org/tron/core/net/messagehandler/FetchInvDataMsgHandler.java @@ -28,7 +28,7 @@ import org.tron.protos.Protocol.ReasonCode; import org.tron.protos.Protocol.Transaction; -@Slf4j +@Slf4j(topic = "net") @Component public class FetchInvDataMsgHandler implements TronMsgHandler { diff --git a/src/main/java/org/tron/core/net/messagehandler/InventoryMsgHandler.java b/src/main/java/org/tron/core/net/messagehandler/InventoryMsgHandler.java index 269039d7b6e..99f088ab323 100644 --- a/src/main/java/org/tron/core/net/messagehandler/InventoryMsgHandler.java +++ b/src/main/java/org/tron/core/net/messagehandler/InventoryMsgHandler.java @@ -4,7 +4,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tron.common.utils.Sha256Hash; -import org.tron.core.config.args.Args; import org.tron.core.net.TronNetDelegate; import org.tron.core.net.message.InventoryMessage; import org.tron.core.net.message.TronMessage; @@ -13,7 +12,7 @@ import org.tron.core.net.service.AdvService; import org.tron.protos.Protocol.Inventory.InventoryType; -@Slf4j +@Slf4j(topic = "net") @Component public class InventoryMsgHandler implements TronMsgHandler { @@ -28,17 +27,11 @@ public class InventoryMsgHandler implements TronMsgHandler { private int maxCountIn10s = 10_000; - private boolean fastForward = Args.getInstance().isFastForward(); - @Override public void processMessage(PeerConnection peer, TronMessage msg) { InventoryMessage inventoryMessage = (InventoryMessage) msg; InventoryType type = inventoryMessage.getInventoryType(); - if (fastForward && inventoryMessage.getInventoryType().equals(InventoryType.TRX)) { - return; - } - if (!check(peer, inventoryMessage)) { return; } @@ -54,10 +47,6 @@ private boolean check(PeerConnection peer, InventoryMessage inventoryMessage) { InventoryType type = inventoryMessage.getInventoryType(); int size = inventoryMessage.getHashList().size(); -// if (size > NetConstants.MAX_INV_FETCH_PER_PEER) { -// throw new P2pException(TypeEnum.BAD_MESSAGE, "size: " + size); -// } - if (peer.isNeedSyncFromPeer() || peer.isNeedSyncFromUs()) { logger.warn("Drop inv: {} size: {} from Peer {}, syncFromUs: {}, syncFromPeer: {}.", type, size, peer.getInetAddress(), peer.isNeedSyncFromUs(), peer.isNeedSyncFromPeer()); diff --git a/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java b/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java index c690e72d762..13cd1a0f0e6 100644 --- a/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java +++ b/src/main/java/org/tron/core/net/messagehandler/SyncBlockChainMsgHandler.java @@ -16,7 +16,7 @@ import org.tron.core.net.message.TronMessage; import org.tron.core.net.peer.PeerConnection; -@Slf4j +@Slf4j(topic = "net") @Component public class SyncBlockChainMsgHandler implements TronMsgHandler { @@ -42,12 +42,6 @@ public void processMessage(PeerConnection peer, TronMessage msg) throws P2pExcep peer.setNeedSyncFromUs(true); remainNum = tronNetDelegate.getHeadBlockId().getNum() - blockIds.peekLast().getNum(); } -// -// if (!peer.isNeedSyncFromPeer() -// && !tronNetDelegate.contain(Iterables.getLast(summaryChainIds), MessageTypes.BLOCK) -// && tronNetDelegate.canChainRevoke(summaryChainIds.get(0).getNum())) { -// //startSyncWithPeer(peer); -// } peer.setLastSyncBlockId(blockIds.peekLast()); peer.setRemainNum(remainNum); @@ -89,6 +83,10 @@ private LinkedList getLostBlockIds(List blockIds) throws P2pEx } } + if (unForkId == null) { + throw new P2pException(TypeEnum.SYNC_FAILED, "unForkId is null"); + } + long len = Math.min(tronNetDelegate.getHeadBlockId().getNum(), unForkId.getNum() + NodeConstant.SYNC_FETCH_BATCH_NUM); diff --git a/src/main/java/org/tron/core/net/peer/PeerStatusCheck.java b/src/main/java/org/tron/core/net/peer/PeerStatusCheck.java index 793d4753840..a07f6c39e94 100644 --- a/src/main/java/org/tron/core/net/peer/PeerStatusCheck.java +++ b/src/main/java/org/tron/core/net/peer/PeerStatusCheck.java @@ -10,7 +10,7 @@ import org.tron.core.net.TronNetDelegate; import org.tron.protos.Protocol.ReasonCode; -@Slf4j +@Slf4j(topic = "net") @Component public class PeerStatusCheck { diff --git a/src/main/java/org/tron/core/net/service/AdvService.java b/src/main/java/org/tron/core/net/service/AdvService.java index 9673c4b7250..36e74cb77a4 100644 --- a/src/main/java/org/tron/core/net/service/AdvService.java +++ b/src/main/java/org/tron/core/net/service/AdvService.java @@ -10,6 +10,7 @@ import java.util.Comparator; import java.util.HashMap; import java.util.LinkedList; +import java.util.List; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; @@ -35,7 +36,7 @@ import org.tron.core.net.peer.PeerConnection; import org.tron.protos.Protocol.Inventory.InventoryType; -@Slf4j +@Slf4j(topic = "net") @Component public class AdvService { @@ -62,26 +63,31 @@ public class AdvService { @Getter private MessageCount trxCount = new MessageCount(); + private int maxSpreadSize = 1_000; + private boolean fastForward = Args.getInstance().isFastForward(); public void init() { - if (!fastForward) { - spreadExecutor.scheduleWithFixedDelay(() -> { - try { - consumerInvToSpread(); - } catch (Throwable t) { - logger.error("Spread thread error.", t); - } - }, 100, 10, TimeUnit.MILLISECONDS); + + if (fastForward) { + return; } + spreadExecutor.scheduleWithFixedDelay(() -> { + try { + consumerInvToSpread(); + } catch (Throwable t) { + logger.error("Spread thread error.", t); + } + }, 100, 30, TimeUnit.MILLISECONDS); + fetchExecutor.scheduleWithFixedDelay(() -> { try { consumerInvToFetch(); } catch (Throwable t) { logger.error("Fetch thread error.", t); } - }, 100, 10, TimeUnit.MILLISECONDS); + }, 100, 30, TimeUnit.MILLISECONDS); } public void close() { @@ -90,6 +96,11 @@ public void close() { } synchronized public boolean addInv(Item item) { + + if (fastForward && !InventoryType.BLOCK.equals(item.getType())) { + return false; + } + if (invToFetchCache.getIfPresent(item) != null) { return false; } @@ -106,6 +117,11 @@ synchronized public boolean addInv(Item item) { invToFetchCache.put(item, System.currentTimeMillis()); invToFetch.put(item, System.currentTimeMillis()); + + if (InventoryType.BLOCK.equals(item.getType())) { + consumerInvToFetch(); + } + return true; } @@ -118,6 +134,16 @@ public Message getMessage(Item item) { } public void broadcast(Message msg) { + + if (fastForward && !(msg instanceof BlockMessage)) { + return; + } + + if (invToSpread.size() > maxSpreadSize) { + logger.warn("Drop message, type: {}, ID: {}.", msg.getType(), msg.getMessageId()); + return; + } + Item item; if (msg instanceof BlockMessage) { BlockMessage blockMsg = (BlockMessage) msg; @@ -140,11 +166,10 @@ public void broadcast(Message msg) { logger.error("Adv item is neither block nor trx, type: {}", msg.getType()); return; } - synchronized (invToSpread) { - invToSpread.put(item, System.currentTimeMillis()); - } - if (fastForward) { + invToSpread.put(item, System.currentTimeMillis()); + + if (InventoryType.BLOCK.equals(item.getType())) { consumerInvToSpread(); } } @@ -160,9 +185,13 @@ public void onDisconnect(PeerConnection peer) { } }); } + + if (invToFetch.size() > 0) { + consumerInvToFetch(); + } } - private void consumerInvToFetch() { + synchronized private void consumerInvToFetch() { Collection peers = tronNetDelegate.getActivePeer().stream() .filter(peer -> peer.isIdle()) .collect(Collectors.toList()); @@ -195,27 +224,26 @@ private void consumerInvToFetch() { invSender.sendFetch(); } - private void consumerInvToSpread() { - if (invToSpread.isEmpty()) { + synchronized private void consumerInvToSpread() { + + List peers = tronNetDelegate.getActivePeer().stream() + .filter(peer -> !peer.isNeedSyncFromPeer() && !peer.isNeedSyncFromUs()) + .collect(Collectors.toList()); + + if (invToSpread.isEmpty() || peers.isEmpty()) { return; } InvSender invSender = new InvSender(); - HashMap spread = new HashMap<>(); - synchronized (invToSpread) { - spread.putAll(invToSpread); - invToSpread.clear(); - } - tronNetDelegate.getActivePeer().stream() - .filter(peer -> !peer.isNeedSyncFromPeer() && !peer.isNeedSyncFromUs()) - .forEach(peer -> spread.entrySet().stream() - .filter(entry -> peer.getAdvInvReceive().getIfPresent(entry.getKey()) == null - && peer.getAdvInvSpread().getIfPresent(entry.getKey()) == null) - .forEach(entry -> { - peer.getAdvInvSpread().put(entry.getKey(), Time.getCurrentMillis()); - invSender.add(entry.getKey(), peer); - })); + invToSpread.forEach((item, time) -> peers.forEach(peer -> { + if (peer.getAdvInvReceive().getIfPresent(item) == null && + peer.getAdvInvSpread().getIfPresent(item) == null) { + peer.getAdvInvSpread().put(item, Time.getCurrentMillis()); + invSender.add(item, peer); + } + invToSpread.remove(item); + })); invSender.sendInv(); } diff --git a/src/main/java/org/tron/core/net/service/SyncService.java b/src/main/java/org/tron/core/net/service/SyncService.java index da55848aa15..6168a2a808d 100644 --- a/src/main/java/org/tron/core/net/service/SyncService.java +++ b/src/main/java/org/tron/core/net/service/SyncService.java @@ -33,7 +33,7 @@ import org.tron.protos.Protocol.Inventory.InventoryType; import org.tron.protos.Protocol.ReasonCode; -@Slf4j +@Slf4j(topic = "net") @Component public class SyncService { diff --git a/src/main/java/org/tron/core/services/RpcApiService.java b/src/main/java/org/tron/core/services/RpcApiService.java index 15c43890dbd..01bc98e0985 100755 --- a/src/main/java/org/tron/core/services/RpcApiService.java +++ b/src/main/java/org/tron/core/services/RpcApiService.java @@ -81,6 +81,7 @@ import org.tron.protos.Contract.AccountCreateContract; import org.tron.protos.Contract.AccountPermissionUpdateContract; import org.tron.protos.Contract.AssetIssueContract; +import org.tron.protos.Contract.ClearABIContract; import org.tron.protos.Contract.ParticipateAssetIssueContract; import org.tron.protos.Contract.TransferAssetContract; import org.tron.protos.Contract.TransferContract; @@ -947,6 +948,13 @@ public void updateEnergyLimit(UpdateEnergyLimitContract request, responseObserver); } + @Override + public void clearContractABI(ClearABIContract request, + StreamObserver responseObserver) { + createTransactionExtention(request, ContractType.ClearABIContract, + responseObserver); + } + @Override public void createWitness(WitnessCreateContract request, StreamObserver responseObserver) { @@ -1515,12 +1523,30 @@ public void getAssetIssueList(EmptyMessage request, @Override public void triggerContract(Contract.TriggerSmartContract request, StreamObserver responseObserver) { + + callContract(request, responseObserver, false); + } + + @Override + public void triggerConstantContract(Contract.TriggerSmartContract request, + StreamObserver responseObserver) { + + callContract(request, responseObserver, true); + } + + private void callContract(Contract.TriggerSmartContract request, + StreamObserver responseObserver, boolean isConstant) { TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); Return.Builder retBuilder = Return.newBuilder(); try { TransactionCapsule trxCap = createTransactionCapsule(request, ContractType.TriggerSmartContract); - Transaction trx = wallet.triggerContract(request, trxCap, trxExtBuilder, retBuilder); + Transaction trx; + if (isConstant) { + trx = wallet.triggerConstantContract(request, trxCap, trxExtBuilder, retBuilder); + } else { + trx = wallet.triggerContract(request, trxCap, trxExtBuilder, retBuilder); + } trxExtBuilder.setTransaction(trx); trxExtBuilder.setTxid(trxCap.getTransactionId().getByteString()); retBuilder.setResult(true).setCode(response_code.SUCCESS); @@ -1684,7 +1710,8 @@ public void blockUntilShutdown() { try { apiServer.awaitTermination(); } catch (InterruptedException e) { - logger.debug(e.getMessage(), e); + logger.warn("{}", e); + Thread.currentThread().interrupt(); } } } diff --git a/src/main/java/org/tron/core/services/WitnessService.java b/src/main/java/org/tron/core/services/WitnessService.java index aa8b155fbf2..00d447974be 100755 --- a/src/main/java/org/tron/core/services/WitnessService.java +++ b/src/main/java/org/tron/core/services/WitnessService.java @@ -54,6 +54,7 @@ public class WitnessService implements Service { .newHashMap(); // private Thread generateThread; + @Getter private volatile boolean isRunning = false; private Map privateKeyMap = Maps .newHashMap();// @@ -129,10 +130,6 @@ public WitnessService(Application tronApp, TronApplicationContext context) { Thread.sleep(timeToNextSecond); } this.blockProductionLoop(); - } catch (InterruptedException ex) { - logger.info("ProductionLoop interrupted"); - } catch (Exception ex) { - logger.error("unknown exception happened in witness loop", ex); } catch (Throwable throwable) { logger.error("unknown throwable happened in witness loop", throwable); } @@ -259,23 +256,23 @@ private BlockProductionCondition tryProduceBlock() throws InterruptedException { block = generateBlock(scheduledTime, scheduledWitness, controller.lastHeadBlockIsMaintenance()); - } - if (block == null) { - logger.warn("exception when generate block"); - return BlockProductionCondition.EXCEPTION_PRODUCING_BLOCK; - } + if (block == null) { + logger.warn("exception when generate block"); + return BlockProductionCondition.EXCEPTION_PRODUCING_BLOCK; + } - int blockProducedTimeOut = Args.getInstance().getBlockProducedTimeOut(); + int blockProducedTimeOut = Args.getInstance().getBlockProducedTimeOut(); - long timeout = Math - .min(ChainConstant.BLOCK_PRODUCED_INTERVAL * blockProducedTimeOut / 100 + 500, - ChainConstant.BLOCK_PRODUCED_INTERVAL); - if (DateTime.now().getMillis() - now > timeout) { - logger.warn("Task timeout ( > {}ms),startTime:{},endTime:{}", timeout, new DateTime(now), - DateTime.now()); - tronApp.getDbManager().eraseBlock(); - return BlockProductionCondition.TIME_OUT; + long timeout = Math + .min(ChainConstant.BLOCK_PRODUCED_INTERVAL * blockProducedTimeOut / 100 + 500, + ChainConstant.BLOCK_PRODUCED_INTERVAL); + if (DateTime.now().getMillis() - now > timeout) { + logger.warn("Task timeout ( > {}ms),startTime:{},endTime:{}", timeout, new DateTime(now), + DateTime.now()); + tronApp.getDbManager().eraseBlock(); + return BlockProductionCondition.TIME_OUT; + } } logger.info( diff --git a/src/main/java/org/tron/core/services/http/AccountPermissionUpdateServlet.java b/src/main/java/org/tron/core/services/http/AccountPermissionUpdateServlet.java index b89f50fc3f4..81076fb2982 100644 --- a/src/main/java/org/tron/core/services/http/AccountPermissionUpdateServlet.java +++ b/src/main/java/org/tron/core/services/http/AccountPermissionUpdateServlet.java @@ -1,5 +1,6 @@ package org.tron.core.services.http; +import com.alibaba.fastjson.JSONObject; import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; @@ -30,13 +31,16 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String contract = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(contract); + boolean visible = Util.getVisiblePost(contract); AccountPermissionUpdateContract.Builder build = AccountPermissionUpdateContract.newBuilder(); - JsonFormat.merge(contract, build); + JsonFormat.merge(contract, build, visible); Transaction tx = wallet .createTransactionCapsule(build.build(), ContractType.AccountPermissionUpdateContract) .getInstance(); - response.getWriter().println(Util.printTransaction(tx)); + JSONObject jsonObject = JSONObject.parseObject(contract); + tx = Util.setTransactionPermissionId(jsonObject, tx); + response.getWriter().println(Util.printCreateTransaction(tx, visible)); } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); try { diff --git a/src/main/java/org/tron/core/services/http/AddTransactionSignServlet.java b/src/main/java/org/tron/core/services/http/AddTransactionSignServlet.java index 6dc45ec608a..3c790e6237f 100644 --- a/src/main/java/org/tron/core/services/http/AddTransactionSignServlet.java +++ b/src/main/java/org/tron/core/services/http/AddTransactionSignServlet.java @@ -15,6 +15,7 @@ import org.tron.protos.Protocol.TransactionSign; + @Component @Slf4j(topic = "API") public class AddTransactionSignServlet extends HttpServlet { @@ -32,15 +33,17 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(contract); JSONObject input = JSONObject.parseObject(contract); + boolean visible = Util.getVisibleOnlyForSign(input); String strTransaction = input.getJSONObject("transaction").toJSONString(); - Transaction transaction = Util.packTransaction(strTransaction); - JSONObject jsonTransaction = JSONObject.parseObject(JsonFormat.printToString(transaction)); + Transaction transaction = Util.packTransaction(strTransaction, visible); + JSONObject jsonTransaction = JSONObject.parseObject(JsonFormat.printToString(transaction, + visible)); input.put("transaction", jsonTransaction); TransactionSign.Builder build = TransactionSign.newBuilder(); - JsonFormat.merge(input.toJSONString(), build); + JsonFormat.merge(input.toJSONString(), build, visible); TransactionCapsule reply = wallet.addSign(build.build()); if (reply != null) { - response.getWriter().println(Util.printTransaction(reply.getInstance())); + response.getWriter().println(Util.printCreateTransaction(reply.getInstance(), visible)); } else { response.getWriter().println("{}"); } diff --git a/src/main/java/org/tron/core/services/http/BroadcastServlet.java b/src/main/java/org/tron/core/services/http/BroadcastServlet.java index f030cf985be..ba08f7ef3c4 100644 --- a/src/main/java/org/tron/core/services/http/BroadcastServlet.java +++ b/src/main/java/org/tron/core/services/http/BroadcastServlet.java @@ -5,6 +5,7 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -12,6 +13,7 @@ import org.tron.core.Wallet; import org.tron.protos.Protocol.Transaction; + @Component @Slf4j(topic = "API") public class BroadcastServlet extends HttpServlet { @@ -24,9 +26,10 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String input = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); - Transaction transaction = Util.packTransaction(input); + boolean visible = Util.getVisiblePost(input); + Transaction transaction = Util.packTransaction(input, visible); GrpcAPI.Return retur = wallet.broadcastTransaction(transaction); - response.getWriter().println(JsonFormat.printToString(retur)); + response.getWriter().println(JsonFormat.printToString(retur, visible)); } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); try { diff --git a/src/main/java/org/tron/core/services/http/ClearABIServlet.java b/src/main/java/org/tron/core/services/http/ClearABIServlet.java new file mode 100644 index 00000000000..b1efbbb87f6 --- /dev/null +++ b/src/main/java/org/tron/core/services/http/ClearABIServlet.java @@ -0,0 +1,54 @@ +package org.tron.core.services.http; + +import com.alibaba.fastjson.JSONObject; + +import java.io.IOException; +import java.util.stream.Collectors; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.Wallet; +import org.tron.protos.Contract.ClearABIContract; +import org.tron.protos.Protocol.Transaction; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; + + +@Component +@Slf4j(topic = "API") +public class ClearABIServlet extends HttpServlet { + + @Autowired + private Wallet wallet; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + try { + String contract = request.getReader().lines() + .collect(Collectors.joining(System.lineSeparator())); + Util.checkBodySize(contract); + boolean visible = Util.getVisiblePost(contract); + ClearABIContract.Builder build = ClearABIContract.newBuilder(); + JsonFormat.merge(contract, build, visible); + Transaction tx = wallet + .createTransactionCapsule(build.build(), ContractType.ClearABIContract) + .getInstance(); + JSONObject jsonObject = JSONObject.parseObject(contract); + tx = Util.setTransactionPermissionId(jsonObject, tx); + response.getWriter().println(Util.printCreateTransaction(tx, visible)); + } catch (Exception e) { + logger.debug("Exception: {}", e.getMessage()); + try { + response.getWriter().println(Util.printErrorMsg(e)); + } catch (IOException ioe) { + logger.debug("IOException: {}", ioe.getMessage()); + } + } + } +} diff --git a/src/main/java/org/tron/core/services/http/CreateAccountServlet.java b/src/main/java/org/tron/core/services/http/CreateAccountServlet.java index 005ef902322..845a8d01cb4 100644 --- a/src/main/java/org/tron/core/services/http/CreateAccountServlet.java +++ b/src/main/java/org/tron/core/services/http/CreateAccountServlet.java @@ -1,10 +1,13 @@ package org.tron.core.services.http; +import com.alibaba.fastjson.JSONObject; + import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -26,12 +29,16 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String contract = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(contract); + boolean visible = Util.getVisiblePost(contract); AccountCreateContract.Builder build = AccountCreateContract.newBuilder(); - JsonFormat.merge(contract, build); + JsonFormat.merge(contract, build, visible); Transaction tx = wallet .createTransactionCapsule(build.build(), ContractType.AccountCreateContract) .getInstance(); - response.getWriter().println(Util.printTransaction(tx)); + + JSONObject input = JSONObject.parseObject(contract); + tx = Util.setTransactionPermissionId(input, tx); + response.getWriter().println(Util.printCreateTransaction(tx, visible)); } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); try { diff --git a/src/main/java/org/tron/core/services/http/CreateAddressServlet.java b/src/main/java/org/tron/core/services/http/CreateAddressServlet.java index ceea51e4f86..589b94e4dd1 100644 --- a/src/main/java/org/tron/core/services/http/CreateAddressServlet.java +++ b/src/main/java/org/tron/core/services/http/CreateAddressServlet.java @@ -1,11 +1,13 @@ package org.tron.core.services.http; import com.alibaba.fastjson.JSONObject; + import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -23,11 +25,15 @@ public class CreateAddressServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { + boolean visible = Util.getVisible(request); String input = request.getParameter("value"); + if (visible) { + input = Util.getHexString(input); + } JSONObject jsonObject = new JSONObject(); jsonObject.put("value", input); BytesMessage.Builder build = BytesMessage.newBuilder(); - JsonFormat.merge(jsonObject.toJSONString(), build); + JsonFormat.merge(jsonObject.toJSONString(), build, visible); byte[] address = wallet.createAdresss(build.getValue().toByteArray()); String base58check = Wallet.encode58Check(address); String hexString = ByteArray.toHexString(address); @@ -45,13 +51,24 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) { } } + private String covertStringToHex(String input) { + JSONObject jsonObject = JSONObject.parseObject(input); + String value = jsonObject.getString("value"); + jsonObject.put("value", Util.getHexString(value)); + return jsonObject.toJSONString(); + } + protected void doPost(HttpServletRequest request, HttpServletResponse response) { try { String input = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); + boolean visible = Util.getVisiblePost(input); + if (visible) { + input = covertStringToHex(input); + } BytesMessage.Builder build = BytesMessage.newBuilder(); - JsonFormat.merge(input, build); + JsonFormat.merge(input, build, visible); byte[] address = wallet.createAdresss(build.getValue().toByteArray()); String base58check = Wallet.encode58Check(address); String hexString = ByteArray.toHexString(address); diff --git a/src/main/java/org/tron/core/services/http/CreateAssetIssueServlet.java b/src/main/java/org/tron/core/services/http/CreateAssetIssueServlet.java index 6115e20211a..f45b2d8f212 100644 --- a/src/main/java/org/tron/core/services/http/CreateAssetIssueServlet.java +++ b/src/main/java/org/tron/core/services/http/CreateAssetIssueServlet.java @@ -1,5 +1,6 @@ package org.tron.core.services.http; +import com.alibaba.fastjson.JSONObject; import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; @@ -30,11 +31,14 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String contract = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(contract); + boolean visible = Util.getVisiblePost(contract); AssetIssueContract.Builder build = AssetIssueContract.newBuilder(); - JsonFormat.merge(contract, build); + JsonFormat.merge(contract, build, visible); Transaction tx = wallet .createTransactionCapsule(build.build(), ContractType.AssetIssueContract).getInstance(); - response.getWriter().println(Util.printTransaction(tx)); + JSONObject jsonObject = JSONObject.parseObject(contract); + tx = Util.setTransactionPermissionId(jsonObject, tx); + response.getWriter().println(Util.printCreateTransaction(tx, visible)); } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); try { diff --git a/src/main/java/org/tron/core/services/http/CreateWitnessServlet.java b/src/main/java/org/tron/core/services/http/CreateWitnessServlet.java index eeb35a919dd..bb0e9bf7975 100644 --- a/src/main/java/org/tron/core/services/http/CreateWitnessServlet.java +++ b/src/main/java/org/tron/core/services/http/CreateWitnessServlet.java @@ -1,5 +1,6 @@ package org.tron.core.services.http; +import com.alibaba.fastjson.JSONObject; import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; @@ -30,12 +31,15 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String contract = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(contract); + boolean visible = Util.getVisiblePost(contract); WitnessCreateContract.Builder build = WitnessCreateContract.newBuilder(); - JsonFormat.merge(contract, build); + JsonFormat.merge(contract, build, visible); Transaction tx = wallet .createTransactionCapsule(build.build(), ContractType.WitnessCreateContract) .getInstance(); - response.getWriter().println(Util.printTransaction(tx)); + JSONObject jsonObject = JSONObject.parseObject(contract); + tx = Util.setTransactionPermissionId(jsonObject, tx); + response.getWriter().println(Util.printCreateTransaction(tx, visible)); } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); try { diff --git a/src/main/java/org/tron/core/services/http/DeployContractServlet.java b/src/main/java/org/tron/core/services/http/DeployContractServlet.java index 78b5bc78a1d..34f26aa4323 100644 --- a/src/main/java/org/tron/core/services/http/DeployContractServlet.java +++ b/src/main/java/org/tron/core/services/http/DeployContractServlet.java @@ -1,5 +1,9 @@ package org.tron.core.services.http; +import static org.tron.core.services.http.Util.getHexAddress; +import static org.tron.core.services.http.Util.getVisiblePost; +import static org.tron.core.services.http.Util.setTransactionPermissionId; + import com.alibaba.fastjson.JSONObject; import com.google.common.base.Strings; import com.google.protobuf.ByteString; @@ -36,30 +40,35 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String contract = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(contract); + boolean visible = getVisiblePost(contract); CreateSmartContract.Builder build = CreateSmartContract.newBuilder(); JSONObject jsonObject = JSONObject.parseObject(contract); - byte[] ownerAddress = ByteArray.fromHexString(jsonObject.getString("owner_address")); + String owner_address = jsonObject.getString("owner_address"); + if (visible) { + owner_address = getHexAddress(owner_address); + } + byte[] ownerAddress = ByteArray.fromHexString(owner_address); build.setOwnerAddress(ByteString.copyFrom(ownerAddress)); - build - .setCallTokenValue(jsonObject.getLongValue("call_token_value")) - .setTokenId(jsonObject.getLongValue("token_id")); + build.setCallTokenValue(Util.getJsonLongValue(jsonObject, "call_token_value")) + .setTokenId(Util.getJsonLongValue(jsonObject, "token_id")); - String abi = jsonObject.getString("abi"); - StringBuffer abiSB = new StringBuffer("{"); - abiSB.append("\"entrys\":"); - abiSB.append(abi); - abiSB.append("}"); ABI.Builder abiBuilder = ABI.newBuilder(); - JsonFormat.merge(abiSB.toString(), abiBuilder); - - long feeLimit = jsonObject.getLongValue("fee_limit"); + if (jsonObject.containsKey("abi")) { + String abi = jsonObject.getString("abi"); + StringBuffer abiSB = new StringBuffer("{"); + abiSB.append("\"entrys\":"); + abiSB.append(abi); + abiSB.append("}"); + JsonFormat.merge(abiSB.toString(), abiBuilder, visible); + } SmartContract.Builder smartBuilder = SmartContract.newBuilder(); smartBuilder .setAbi(abiBuilder) - .setCallValue(jsonObject.getLongValue("call_value")) - .setConsumeUserResourcePercent(jsonObject.getLongValue("consume_user_resource_percent")) - .setOriginEnergyLimit(jsonObject.getLongValue("origin_energy_limit")); + .setCallValue(Util.getJsonLongValue(jsonObject, "call_value")) + .setConsumeUserResourcePercent(Util.getJsonLongValue(jsonObject, + "consume_user_resource_percent")) + .setOriginEnergyLimit(Util.getJsonLongValue(jsonObject, "origin_energy_limit")); if (!ArrayUtils.isEmpty(ownerAddress)) { smartBuilder.setOriginAddress(ByteString.copyFrom(ownerAddress)); } @@ -77,6 +86,7 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) smartBuilder.setName(name); } + long feeLimit = Util.getJsonLongValue(jsonObject, "fee_limit"); build.setNewContract(smartBuilder); Transaction tx = wallet .createTransactionCapsule(build.build(), ContractType.CreateSmartContract).getInstance(); @@ -84,7 +94,8 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) Transaction.raw.Builder rawBuilder = tx.getRawData().toBuilder(); rawBuilder.setFeeLimit(feeLimit); txBuilder.setRawData(rawBuilder); - response.getWriter().println(Util.printTransaction(txBuilder.build())); + tx = setTransactionPermissionId(jsonObject, txBuilder.build()); + response.getWriter().println(Util.printCreateTransaction(tx, visible)); } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); try { diff --git a/src/main/java/org/tron/core/services/http/EasyTransferAssetByPrivateServlet.java b/src/main/java/org/tron/core/services/http/EasyTransferAssetByPrivateServlet.java index ae3b449a731..0e15c32231f 100644 --- a/src/main/java/org/tron/core/services/http/EasyTransferAssetByPrivateServlet.java +++ b/src/main/java/org/tron/core/services/http/EasyTransferAssetByPrivateServlet.java @@ -1,11 +1,13 @@ package org.tron.core.services.http; import com.google.protobuf.ByteString; + import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -34,12 +36,14 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) { protected void doPost(HttpServletRequest request, HttpServletResponse response) { GrpcAPI.Return.Builder returnBuilder = GrpcAPI.Return.newBuilder(); EasyTransferResponse.Builder responseBuild = EasyTransferResponse.newBuilder(); + boolean visible = false; try { String input = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); + visible = Util.getVisiblePost(input); EasyTransferAssetByPrivateMessage.Builder build = EasyTransferAssetByPrivateMessage .newBuilder(); - JsonFormat.merge(input, build); + JsonFormat.merge(input, build, visible); byte[] privateKey = build.getPrivateKey().toByteArray(); ECKey ecKey = ECKey.fromPrivate(privateKey); byte[] owner = ecKey.getAddress(); @@ -56,13 +60,13 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) GrpcAPI.Return retur = wallet.broadcastTransaction(transactionCapsule.getInstance()); responseBuild.setTransaction(transactionCapsule.getInstance()); responseBuild.setResult(retur); - response.getWriter().println(Util.printEasyTransferResponse(responseBuild.build())); + response.getWriter().println(Util.printEasyTransferResponse(responseBuild.build(), visible)); } catch (Exception e) { returnBuilder.setResult(false).setCode(response_code.CONTRACT_VALIDATE_ERROR) .setMessage(ByteString.copyFromUtf8(e.getMessage())); responseBuild.setResult(returnBuilder.build()); try { - response.getWriter().println(JsonFormat.printToString(responseBuild.build())); + response.getWriter().println(JsonFormat.printToString(responseBuild.build(), visible)); } catch (IOException ioe) { logger.debug("IOException: {}", ioe.getMessage()); } diff --git a/src/main/java/org/tron/core/services/http/EasyTransferAssetServlet.java b/src/main/java/org/tron/core/services/http/EasyTransferAssetServlet.java index 1e0f6b37e05..39cda2a0fd7 100644 --- a/src/main/java/org/tron/core/services/http/EasyTransferAssetServlet.java +++ b/src/main/java/org/tron/core/services/http/EasyTransferAssetServlet.java @@ -1,11 +1,13 @@ package org.tron.core.services.http; import com.google.protobuf.ByteString; + import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -36,11 +38,13 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) { protected void doPost(HttpServletRequest request, HttpServletResponse response) { GrpcAPI.Return.Builder returnBuilder = GrpcAPI.Return.newBuilder(); EasyTransferResponse.Builder responseBuild = EasyTransferResponse.newBuilder(); + boolean visible = false; try { String input = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); + visible = Util.getVisiblePost(input); EasyTransferAssetMessage.Builder build = EasyTransferAssetMessage.newBuilder(); - JsonFormat.merge(input, build); + JsonFormat.merge(input, build, visible); byte[] privateKey = wallet.pass2Key(build.getPassPhrase().toByteArray()); ECKey ecKey = ECKey.fromPrivate(privateKey); byte[] owner = ecKey.getAddress(); @@ -57,14 +61,14 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) GrpcAPI.Return retur = wallet.broadcastTransaction(transactionCapsule.getInstance()); responseBuild.setTransaction(transactionCapsule.getInstance()); responseBuild.setResult(retur); - response.getWriter().println(Util.printEasyTransferResponse(responseBuild.build())); + response.getWriter().println(Util.printEasyTransferResponse(responseBuild.build(), visible)); } catch (ParseException e) { logger.debug("ParseException: {}", e.getMessage()); returnBuilder.setResult(false).setCode(response_code.OTHER_ERROR) .setMessage(ByteString.copyFromUtf8(e.getMessage())); responseBuild.setResult(returnBuilder.build()); try { - response.getWriter().println(JsonFormat.printToString(responseBuild.build())); + response.getWriter().println(JsonFormat.printToString(responseBuild.build(), visible)); } catch (IOException ioe) { logger.debug("IOException: {}", ioe.getMessage()); } @@ -75,7 +79,7 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) .setMessage(ByteString.copyFromUtf8(e.getMessage())); responseBuild.setResult(returnBuilder.build()); try { - response.getWriter().println(JsonFormat.printToString(responseBuild.build())); + response.getWriter().println(JsonFormat.printToString(responseBuild.build(), visible)); } catch (IOException ioe) { logger.debug("IOException: {}", ioe.getMessage()); } @@ -85,7 +89,7 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) .setMessage(ByteString.copyFromUtf8(e.getMessage())); responseBuild.setResult(returnBuilder.build()); try { - response.getWriter().println(JsonFormat.printToString(responseBuild.build())); + response.getWriter().println(JsonFormat.printToString(responseBuild.build(), visible)); } catch (IOException ioe) { logger.debug("IOException: {}", ioe.getMessage()); } diff --git a/src/main/java/org/tron/core/services/http/EasyTransferByPrivateServlet.java b/src/main/java/org/tron/core/services/http/EasyTransferByPrivateServlet.java index b89117d68ab..21240947bdd 100644 --- a/src/main/java/org/tron/core/services/http/EasyTransferByPrivateServlet.java +++ b/src/main/java/org/tron/core/services/http/EasyTransferByPrivateServlet.java @@ -1,11 +1,13 @@ package org.tron.core.services.http; import com.google.protobuf.ByteString; + import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -34,12 +36,14 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) { protected void doPost(HttpServletRequest request, HttpServletResponse response) { GrpcAPI.Return.Builder returnBuilder = GrpcAPI.Return.newBuilder(); EasyTransferResponse.Builder responseBuild = EasyTransferResponse.newBuilder(); + boolean visible = false; try { String input = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); + visible = Util.getVisiblePost(input); EasyTransferByPrivateMessage.Builder build = EasyTransferByPrivateMessage.newBuilder(); - JsonFormat.merge(input, build); + JsonFormat.merge(input, build, visible); byte[] privateKey = build.getPrivateKey().toByteArray(); ECKey ecKey = ECKey.fromPrivate(privateKey); byte[] owner = ecKey.getAddress(); @@ -55,13 +59,13 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) GrpcAPI.Return retur = wallet.broadcastTransaction(transactionCapsule.getInstance()); responseBuild.setTransaction(transactionCapsule.getInstance()); responseBuild.setResult(retur); - response.getWriter().println(Util.printEasyTransferResponse(responseBuild.build())); + response.getWriter().println(Util.printEasyTransferResponse(responseBuild.build(), visible)); } catch (Exception e) { returnBuilder.setResult(false).setCode(response_code.CONTRACT_VALIDATE_ERROR) .setMessage(ByteString.copyFromUtf8(e.getMessage())); responseBuild.setResult(returnBuilder.build()); try { - response.getWriter().println(JsonFormat.printToString(responseBuild.build())); + response.getWriter().println(JsonFormat.printToString(responseBuild.build(), visible)); } catch (IOException ioe) { logger.debug("IOException: {}", ioe.getMessage()); } diff --git a/src/main/java/org/tron/core/services/http/EasyTransferServlet.java b/src/main/java/org/tron/core/services/http/EasyTransferServlet.java index 8da8e026445..dbd585a4e0b 100644 --- a/src/main/java/org/tron/core/services/http/EasyTransferServlet.java +++ b/src/main/java/org/tron/core/services/http/EasyTransferServlet.java @@ -1,11 +1,13 @@ package org.tron.core.services.http; import com.google.protobuf.ByteString; + import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -36,12 +38,14 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) { protected void doPost(HttpServletRequest request, HttpServletResponse response) { GrpcAPI.Return.Builder returnBuilder = GrpcAPI.Return.newBuilder(); EasyTransferResponse.Builder responseBuild = EasyTransferResponse.newBuilder(); + boolean visible = false; try { String input = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); + visible = Util.getVisiblePost(input); EasyTransferMessage.Builder build = EasyTransferMessage.newBuilder(); - JsonFormat.merge(input, build); + JsonFormat.merge(input, build, visible); byte[] privateKey = wallet.pass2Key(build.getPassPhrase().toByteArray()); ECKey ecKey = ECKey.fromPrivate(privateKey); byte[] owner = ecKey.getAddress(); @@ -57,7 +61,7 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) GrpcAPI.Return retur = wallet.broadcastTransaction(transactionCapsule.getInstance()); responseBuild.setTransaction(transactionCapsule.getInstance()); responseBuild.setResult(retur); - response.getWriter().println(Util.printEasyTransferResponse(responseBuild.build())); + response.getWriter().println(Util.printEasyTransferResponse(responseBuild.build(), visible)); } catch (ParseException e) { logger.debug("ParseException: {}", e.getMessage()); } catch (IOException e) { @@ -67,7 +71,7 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) .setMessage(ByteString.copyFromUtf8(e.getMessage())); responseBuild.setResult(returnBuilder.build()); try { - response.getWriter().println(JsonFormat.printToString(responseBuild.build())); + response.getWriter().println(JsonFormat.printToString(responseBuild.build(), visible)); } catch (IOException ioe) { logger.debug("IOException: {}", ioe.getMessage()); } diff --git a/src/main/java/org/tron/core/services/http/ExchangeCreateServlet.java b/src/main/java/org/tron/core/services/http/ExchangeCreateServlet.java index 4e77da9d39a..5ccd1133081 100644 --- a/src/main/java/org/tron/core/services/http/ExchangeCreateServlet.java +++ b/src/main/java/org/tron/core/services/http/ExchangeCreateServlet.java @@ -1,5 +1,6 @@ package org.tron.core.services.http; +import com.alibaba.fastjson.JSONObject; import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; @@ -26,12 +27,15 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String contract = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(contract); + boolean visible = Util.getVisiblePost(contract); ExchangeCreateContract.Builder build = ExchangeCreateContract.newBuilder(); - JsonFormat.merge(contract, build); + JsonFormat.merge(contract, build, visible); Transaction tx = wallet .createTransactionCapsule(build.build(), ContractType.ExchangeCreateContract) .getInstance(); - response.getWriter().println(Util.printTransaction(tx)); + JSONObject jsonObject = JSONObject.parseObject(contract); + tx = Util.setTransactionPermissionId(jsonObject, tx); + response.getWriter().println(Util.printCreateTransaction(tx, visible)); } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); try { diff --git a/src/main/java/org/tron/core/services/http/ExchangeInjectServlet.java b/src/main/java/org/tron/core/services/http/ExchangeInjectServlet.java index efc9634e8b2..75a27deb604 100644 --- a/src/main/java/org/tron/core/services/http/ExchangeInjectServlet.java +++ b/src/main/java/org/tron/core/services/http/ExchangeInjectServlet.java @@ -1,5 +1,6 @@ package org.tron.core.services.http; +import com.alibaba.fastjson.JSONObject; import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; @@ -26,12 +27,15 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String contract = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(contract); + boolean visible = Util.getVisiblePost(contract); ExchangeInjectContract.Builder build = ExchangeInjectContract.newBuilder(); - JsonFormat.merge(contract, build); + JsonFormat.merge(contract, build, visible); Transaction tx = wallet .createTransactionCapsule(build.build(), ContractType.ExchangeInjectContract) .getInstance(); - response.getWriter().println(Util.printTransaction(tx)); + JSONObject jsonObject = JSONObject.parseObject(contract); + tx = Util.setTransactionPermissionId(jsonObject, tx); + response.getWriter().println(Util.printCreateTransaction(tx, visible)); } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); try { diff --git a/src/main/java/org/tron/core/services/http/ExchangeTransactionServlet.java b/src/main/java/org/tron/core/services/http/ExchangeTransactionServlet.java index 2b748345e22..fc5043a25e2 100644 --- a/src/main/java/org/tron/core/services/http/ExchangeTransactionServlet.java +++ b/src/main/java/org/tron/core/services/http/ExchangeTransactionServlet.java @@ -1,5 +1,6 @@ package org.tron.core.services.http; +import com.alibaba.fastjson.JSONObject; import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; @@ -26,12 +27,15 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String contract = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(contract); + boolean visible = Util.getVisiblePost(contract); ExchangeTransactionContract.Builder build = ExchangeTransactionContract.newBuilder(); - JsonFormat.merge(contract, build); + JsonFormat.merge(contract, build, visible); Transaction tx = wallet .createTransactionCapsule(build.build(), ContractType.ExchangeTransactionContract) .getInstance(); - response.getWriter().println(Util.printTransaction(tx)); + JSONObject jsonObject = JSONObject.parseObject(contract); + tx = Util.setTransactionPermissionId(jsonObject, tx); + response.getWriter().println(Util.printCreateTransaction(tx, visible)); } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); try { diff --git a/src/main/java/org/tron/core/services/http/ExchangeWithdrawServlet.java b/src/main/java/org/tron/core/services/http/ExchangeWithdrawServlet.java index e7b549116e4..6af783cecbe 100644 --- a/src/main/java/org/tron/core/services/http/ExchangeWithdrawServlet.java +++ b/src/main/java/org/tron/core/services/http/ExchangeWithdrawServlet.java @@ -1,5 +1,6 @@ package org.tron.core.services.http; +import com.alibaba.fastjson.JSONObject; import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; @@ -26,12 +27,15 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String contract = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(contract); + boolean visible = Util.getVisiblePost(contract); ExchangeWithdrawContract.Builder build = ExchangeWithdrawContract.newBuilder(); - JsonFormat.merge(contract, build); + JsonFormat.merge(contract, build, visible); Transaction tx = wallet .createTransactionCapsule(build.build(), ContractType.ExchangeWithdrawContract) .getInstance(); - response.getWriter().println(Util.printTransaction(tx)); + JSONObject jsonObject = JSONObject.parseObject(contract); + tx = Util.setTransactionPermissionId(jsonObject, tx); + response.getWriter().println(Util.printCreateTransaction(tx, visible)); } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); try { diff --git a/src/main/java/org/tron/core/services/http/FreezeBalanceServlet.java b/src/main/java/org/tron/core/services/http/FreezeBalanceServlet.java index a61e7012978..75c3b13c39e 100644 --- a/src/main/java/org/tron/core/services/http/FreezeBalanceServlet.java +++ b/src/main/java/org/tron/core/services/http/FreezeBalanceServlet.java @@ -1,5 +1,6 @@ package org.tron.core.services.http; +import com.alibaba.fastjson.JSONObject; import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; @@ -26,12 +27,15 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String contract = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(contract); + boolean visible = Util.getVisiblePost(contract); FreezeBalanceContract.Builder build = FreezeBalanceContract.newBuilder(); - JsonFormat.merge(contract, build); + JsonFormat.merge(contract, build, visible); Transaction tx = wallet .createTransactionCapsule(build.build(), ContractType.FreezeBalanceContract) .getInstance(); - response.getWriter().println(Util.printTransaction(tx)); + JSONObject jsonObject = JSONObject.parseObject(contract); + tx = Util.setTransactionPermissionId(jsonObject, tx); + response.getWriter().println(Util.printCreateTransaction(tx, visible)); } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); try { diff --git a/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java b/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java index 0400ae42140..99e8e270b16 100644 --- a/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java +++ b/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java @@ -1,6 +1,7 @@ package org.tron.core.services.http; import lombok.extern.slf4j.Slf4j; +import org.eclipse.jetty.server.ConnectionLimit; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; @@ -112,8 +113,12 @@ public class FullNodeHttpApiService implements Service { @Autowired private TriggerSmartContractServlet triggerSmartContractServlet; @Autowired + private TriggerConstantContractServlet triggerConstantContractServlet; + @Autowired private GetContractServlet getContractServlet; @Autowired + private ClearABIServlet clearABIServlet; + @Autowired private ProposalCreateServlet proposalCreateServlet; @Autowired private ProposalApproveServlet proposalApproveServlet; @@ -157,6 +162,11 @@ public class FullNodeHttpApiService implements Service { private GetDelegatedResourceAccountIndexServlet getDelegatedResourceAccountIndexServlet; @Autowired private GetDelegatedResourceServlet getDelegatedResourceServlet; + @Autowired + private SetAccountIdServlet setAccountServlet; + @Autowired + private GetAccountByIdServlet getAccountByIdServlet; + @Override public void init() { @@ -206,6 +216,7 @@ public void start() { context.addServlet(new ServletHolder(getBlockByLimitNextServlet), "/getblockbylimitnext"); context.addServlet(new ServletHolder(getBlockByLatestNumServlet), "/getblockbylatestnum"); context.addServlet(new ServletHolder(getTransactionByIdServlet), "/gettransactionbyid"); + context.addServlet( new ServletHolder(getTransactionInfoByIdServlet), "/gettransactioninfobyid"); context.addServlet( @@ -232,7 +243,10 @@ public void start() { context.addServlet(new ServletHolder(validateAddressServlet), "/validateaddress"); context.addServlet(new ServletHolder(deployContractServlet), "/deploycontract"); context.addServlet(new ServletHolder(triggerSmartContractServlet), "/triggersmartcontract"); + context.addServlet(new ServletHolder(triggerConstantContractServlet), + "/triggerconstantcontract"); context.addServlet(new ServletHolder(getContractServlet), "/getcontract"); + context.addServlet(new ServletHolder(clearABIServlet), "/clearabi"); context.addServlet(new ServletHolder(proposalCreateServlet), "/proposalcreate"); context.addServlet(new ServletHolder(proposalApproveServlet), "/proposalapprove"); context.addServlet(new ServletHolder(proposalDeleteServlet), "/proposaldelete"); @@ -258,6 +272,13 @@ public void start() { context.addServlet( new ServletHolder(getDelegatedResourceAccountIndexServlet), "/getdelegatedresourceaccountindex"); + context.addServlet(new ServletHolder(setAccountServlet), "/setaccountid"); + context.addServlet(new ServletHolder(getAccountByIdServlet), "/getaccountbyid"); + + int maxHttpConnectNumber = Args.getInstance().getMaxHttpConnectNumber(); + if (maxHttpConnectNumber > 0) { + server.addBean(new ConnectionLimit(maxHttpConnectNumber, server)); + } server.start(); } catch (Exception e) { diff --git a/src/main/java/org/tron/core/services/http/GenerateAddressServlet.java b/src/main/java/org/tron/core/services/http/GenerateAddressServlet.java index 51e2898948a..aa2521634b0 100644 --- a/src/main/java/org/tron/core/services/http/GenerateAddressServlet.java +++ b/src/main/java/org/tron/core/services/http/GenerateAddressServlet.java @@ -1,10 +1,12 @@ package org.tron.core.services.http; import com.alibaba.fastjson.JSONObject; + import java.io.IOException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.binary.Hex; import org.springframework.stereotype.Component; diff --git a/src/main/java/org/tron/core/services/http/GetAccountByIdServlet.java b/src/main/java/org/tron/core/services/http/GetAccountByIdServlet.java index 535dd48cb90..151cc2abe28 100644 --- a/src/main/java/org/tron/core/services/http/GetAccountByIdServlet.java +++ b/src/main/java/org/tron/core/services/http/GetAccountByIdServlet.java @@ -2,11 +2,13 @@ import com.alibaba.fastjson.JSONObject; import com.google.protobuf.ByteString; + import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -14,6 +16,7 @@ import org.tron.core.Wallet; import org.tron.protos.Protocol.Account; + @Component @Slf4j(topic = "API") public class GetAccountByIdServlet extends HttpServlet { @@ -24,28 +27,32 @@ public class GetAccountByIdServlet extends HttpServlet { private String convertOutput(Account account) { // convert asset id if (account.getAssetIssuedID().isEmpty()) { - return JsonFormat.printToString(account); + return JsonFormat.printToString(account, false); } else { - JSONObject accountJson = JSONObject.parseObject(JsonFormat.printToString(account)); + JSONObject accountJson = JSONObject.parseObject(JsonFormat.printToString(account, false)); String assetId = accountJson.get("asset_issued_ID").toString(); accountJson.put( "asset_issued_ID", ByteString.copyFrom(ByteArray.fromHexString(assetId)).toStringUtf8()); return accountJson.toJSONString(); } - } protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { - String accountId = request.getParameter("accountId"); + boolean visible = Util.getVisible(request); + String accountId = request.getParameter("account_id"); Account.Builder build = Account.newBuilder(); JSONObject jsonObject = new JSONObject(); - jsonObject.put("accountId", accountId); - JsonFormat.merge(jsonObject.toJSONString(), build); + jsonObject.put("account_id", accountId); + JsonFormat.merge(jsonObject.toJSONString(), build, visible); Account reply = wallet.getAccountById(build.build()); if (reply != null) { - response.getWriter().println(convertOutput(reply)); + if (visible) { + response.getWriter().println(JsonFormat.printToString(reply, true)); + } else { + response.getWriter().println(convertOutput(reply)); + } } else { response.getWriter().println("{}"); } @@ -64,12 +71,17 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String account = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(account); + boolean visible = Util.getVisiblePost(account); Account.Builder build = Account.newBuilder(); - JsonFormat.merge(account, build); + JsonFormat.merge(account, build, visible); Account reply = wallet.getAccountById(build.build()); if (reply != null) { - response.getWriter().println(convertOutput(reply)); + if (visible) { + response.getWriter().println(JsonFormat.printToString(reply, true)); + } else { + response.getWriter().println(convertOutput(reply)); + } } else { response.getWriter().println("{}"); } diff --git a/src/main/java/org/tron/core/services/http/GetAccountNetServlet.java b/src/main/java/org/tron/core/services/http/GetAccountNetServlet.java index dc578111573..58dfca1c068 100644 --- a/src/main/java/org/tron/core/services/http/GetAccountNetServlet.java +++ b/src/main/java/org/tron/core/services/http/GetAccountNetServlet.java @@ -1,11 +1,13 @@ package org.tron.core.services.http; import com.google.protobuf.ByteString; + import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -24,11 +26,15 @@ public class GetAccountNetServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { + boolean visible = Util.getVisible(request); String address = request.getParameter("address"); + if (visible) { + address = Util.getHexAddress(address); + } AccountNetMessage reply = wallet .getAccountNet(ByteString.copyFrom(ByteArray.fromHexString(address))); if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply)); + response.getWriter().println(JsonFormat.printToString(reply, visible)); } else { response.getWriter().println("{}"); } @@ -47,11 +53,12 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String account = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(account); + boolean visible = Util.getVisiblePost(account); Account.Builder build = Account.newBuilder(); - JsonFormat.merge(account, build); + JsonFormat.merge(account, build, visible); AccountNetMessage reply = wallet.getAccountNet(build.getAddress()); if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply)); + response.getWriter().println(JsonFormat.printToString(reply, visible)); } else { response.getWriter().println("{}"); } diff --git a/src/main/java/org/tron/core/services/http/GetAccountResourceServlet.java b/src/main/java/org/tron/core/services/http/GetAccountResourceServlet.java index 850c99df1de..112d99a012a 100644 --- a/src/main/java/org/tron/core/services/http/GetAccountResourceServlet.java +++ b/src/main/java/org/tron/core/services/http/GetAccountResourceServlet.java @@ -2,11 +2,13 @@ import com.alibaba.fastjson.JSONObject; import com.google.protobuf.ByteString; + import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -24,11 +26,15 @@ public class GetAccountResourceServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { + boolean visible = Util.getVisible(request); String address = request.getParameter("address"); + if (visible) { + address = Util.getHexAddress(address); + } AccountResourceMessage reply = wallet .getAccountResource(ByteString.copyFrom(ByteArray.fromHexString(address))); if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply)); + response.getWriter().println(JsonFormat.printToString(reply, visible)); } else { response.getWriter().println("{}"); } @@ -47,12 +53,16 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String input = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); + boolean visible = Util.getVisiblePost(input); JSONObject jsonObject = JSONObject.parseObject(input); String address = jsonObject.getString("address"); + if (visible) { + address = Util.getHexAddress(address); + } AccountResourceMessage reply = wallet .getAccountResource(ByteString.copyFrom(ByteArray.fromHexString(address))); if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply)); + response.getWriter().println(JsonFormat.printToString(reply, visible)); } else { response.getWriter().println("{}"); } diff --git a/src/main/java/org/tron/core/services/http/GetAccountServlet.java b/src/main/java/org/tron/core/services/http/GetAccountServlet.java index 68ccad416a5..96b1544084d 100644 --- a/src/main/java/org/tron/core/services/http/GetAccountServlet.java +++ b/src/main/java/org/tron/core/services/http/GetAccountServlet.java @@ -2,11 +2,13 @@ import com.alibaba.fastjson.JSONObject; import com.google.protobuf.ByteString; + import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -29,28 +31,32 @@ public class GetAccountServlet extends HttpServlet { private String convertOutput(Account account) { // convert asset id if (account.getAssetIssuedID().isEmpty()) { - return JsonFormat.printToString(account); + return JsonFormat.printToString(account, false); } else { - JSONObject accountJson = JSONObject.parseObject(JsonFormat.printToString(account)); + JSONObject accountJson = JSONObject.parseObject(JsonFormat.printToString(account, false)); String assetId = accountJson.get("asset_issued_ID").toString(); accountJson.put( "asset_issued_ID", ByteString.copyFrom(ByteArray.fromHexString(assetId)).toStringUtf8()); return accountJson.toJSONString(); } - } protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { + boolean visible = Util.getVisible(request); String address = request.getParameter("address"); Account.Builder build = Account.newBuilder(); JSONObject jsonObject = new JSONObject(); jsonObject.put("address", address); - JsonFormat.merge(jsonObject.toJSONString(), build); + JsonFormat.merge(jsonObject.toJSONString(), build, visible); Account reply = wallet.getAccount(build.build()); if (reply != null) { - response.getWriter().println(convertOutput(reply)); + if (visible) { + response.getWriter().println(JsonFormat.printToString(reply, true)); + } else { + response.getWriter().println(convertOutput(reply)); + } } else { response.getWriter().println("{}"); } @@ -69,12 +75,17 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String account = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(account); + boolean visible = Util.getVisiblePost(account); Account.Builder build = Account.newBuilder(); - JsonFormat.merge(account, build); + JsonFormat.merge(account, build, visible); Account reply = wallet.getAccount(build.build()); if (reply != null) { - response.getWriter().println(convertOutput(reply)); + if (visible) { + response.getWriter().println(JsonFormat.printToString(reply, true)); + } else { + response.getWriter().println(convertOutput(reply)); + } } else { response.getWriter().println("{}"); } diff --git a/src/main/java/org/tron/core/services/http/GetAssetIssueByAccountServlet.java b/src/main/java/org/tron/core/services/http/GetAssetIssueByAccountServlet.java index de2eaa60a6f..45357de623c 100644 --- a/src/main/java/org/tron/core/services/http/GetAssetIssueByAccountServlet.java +++ b/src/main/java/org/tron/core/services/http/GetAssetIssueByAccountServlet.java @@ -1,11 +1,13 @@ package org.tron.core.services.http; import com.google.protobuf.ByteString; + import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -24,11 +26,15 @@ public class GetAssetIssueByAccountServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { + boolean visible = Util.getVisible(request); String address = request.getParameter("address"); + if (visible) { + address = Util.getHexAddress(address); + } AssetIssueList reply = wallet .getAssetIssueByAccount(ByteString.copyFrom(ByteArray.fromHexString(address))); if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply)); + response.getWriter().println(JsonFormat.printToString(reply, visible)); } else { response.getWriter().println("{}"); } @@ -47,11 +53,12 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String account = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(account); + boolean visible = Util.getVisiblePost(account); Account.Builder build = Account.newBuilder(); - JsonFormat.merge(account, build); + JsonFormat.merge(account, build, visible); AssetIssueList reply = wallet.getAssetIssueByAccount(build.getAddress()); if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply)); + response.getWriter().println(JsonFormat.printToString(reply, visible)); } else { response.getWriter().println("{}"); } diff --git a/src/main/java/org/tron/core/services/http/GetAssetIssueByIdServlet.java b/src/main/java/org/tron/core/services/http/GetAssetIssueByIdServlet.java index a5bc0ef6a1e..a12de14f575 100644 --- a/src/main/java/org/tron/core/services/http/GetAssetIssueByIdServlet.java +++ b/src/main/java/org/tron/core/services/http/GetAssetIssueByIdServlet.java @@ -1,17 +1,20 @@ package org.tron.core.services.http; import com.alibaba.fastjson.JSONObject; + import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tron.core.Wallet; import org.tron.protos.Contract.AssetIssueContract; + @Component @Slf4j(topic = "API") public class GetAssetIssueByIdServlet extends HttpServlet { @@ -21,10 +24,11 @@ public class GetAssetIssueByIdServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { + boolean visible = Util.getVisible(request); String input = request.getParameter("value"); AssetIssueContract reply = wallet.getAssetIssueById(input); if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply)); + response.getWriter().println(JsonFormat.printToString(reply, visible)); } else { response.getWriter().println("{}"); } @@ -43,12 +47,12 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String input = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); + boolean visible = Util.getVisiblePost(input); JSONObject jsonObject = JSONObject.parseObject(input); String id = jsonObject.getString("value"); - AssetIssueContract reply = wallet.getAssetIssueById(id); if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply)); + response.getWriter().println(JsonFormat.printToString(reply, visible)); } else { response.getWriter().println("{}"); } diff --git a/src/main/java/org/tron/core/services/http/GetAssetIssueByNameServlet.java b/src/main/java/org/tron/core/services/http/GetAssetIssueByNameServlet.java index f1b37dc1aeb..475feda8206 100644 --- a/src/main/java/org/tron/core/services/http/GetAssetIssueByNameServlet.java +++ b/src/main/java/org/tron/core/services/http/GetAssetIssueByNameServlet.java @@ -1,19 +1,23 @@ package org.tron.core.services.http; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; import com.google.protobuf.ByteString; + import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.tron.api.GrpcAPI.BytesMessage; import org.tron.common.utils.ByteArray; import org.tron.core.Wallet; import org.tron.protos.Contract.AssetIssueContract; + @Component @Slf4j(topic = "API") public class GetAssetIssueByNameServlet extends HttpServlet { @@ -23,12 +27,16 @@ public class GetAssetIssueByNameServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { + boolean visible = Util.getVisible(request); String input = request.getParameter("value"); + if (visible) { + input = Util.getHexString(input); + } AssetIssueContract reply = wallet.getAssetIssueByName(ByteString.copyFrom(ByteArray.fromHexString(input))); if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply)); + response.getWriter().println(JsonFormat.printToString(reply, visible)); } else { response.getWriter().println("{}"); } @@ -47,12 +55,16 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String input = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); - BytesMessage.Builder build = BytesMessage.newBuilder(); - JsonFormat.merge(input, build); - AssetIssueContract reply = wallet.getAssetIssueByName(build.getValue()); - + boolean visible = Util.getVisiblePost(input); + JSONObject jsonObject = JSON.parseObject(input); + String value = jsonObject.getString("value"); + if (visible) { + value = Util.getHexString(value); + } + AssetIssueContract reply = + wallet.getAssetIssueByName(ByteString.copyFrom(ByteArray.fromHexString(value))); if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply)); + response.getWriter().println(JsonFormat.printToString(reply, visible)); } else { response.getWriter().println("{}"); } diff --git a/src/main/java/org/tron/core/services/http/GetAssetIssueListByNameServlet.java b/src/main/java/org/tron/core/services/http/GetAssetIssueListByNameServlet.java index 8ed27089ed9..d491a079544 100644 --- a/src/main/java/org/tron/core/services/http/GetAssetIssueListByNameServlet.java +++ b/src/main/java/org/tron/core/services/http/GetAssetIssueListByNameServlet.java @@ -1,19 +1,23 @@ package org.tron.core.services.http; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; import com.google.protobuf.ByteString; + import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tron.api.GrpcAPI.AssetIssueList; -import org.tron.api.GrpcAPI.BytesMessage; import org.tron.common.utils.ByteArray; import org.tron.core.Wallet; + @Component @Slf4j(topic = "API") public class GetAssetIssueListByNameServlet extends HttpServlet { @@ -23,11 +27,15 @@ public class GetAssetIssueListByNameServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { + boolean visible = Util.getVisible(request); String input = request.getParameter("value"); + if (visible) { + input = Util.getHexString(input); + } AssetIssueList reply = wallet .getAssetIssueListByName(ByteString.copyFrom(ByteArray.fromHexString(input))); if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply)); + response.getWriter().println(JsonFormat.printToString(reply, visible)); } else { response.getWriter().println("{}"); } @@ -46,11 +54,16 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String input = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); - BytesMessage.Builder build = BytesMessage.newBuilder(); - JsonFormat.merge(input, build); - AssetIssueList reply = wallet.getAssetIssueListByName(build.getValue()); + boolean visible = Util.getVisiblePost(input); + JSONObject jsonObject = JSON.parseObject(input); + String value = jsonObject.getString("value"); + if (visible) { + value = Util.getHexString(value); + } + AssetIssueList reply = wallet.getAssetIssueListByName(ByteString.copyFrom( + ByteArray.fromHexString(value))); if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply)); + response.getWriter().println(JsonFormat.printToString(reply, visible)); } else { response.getWriter().println("{}"); } diff --git a/src/main/java/org/tron/core/services/http/GetAssetIssueListServlet.java b/src/main/java/org/tron/core/services/http/GetAssetIssueListServlet.java index 2f742425bd7..36f57cd8c67 100644 --- a/src/main/java/org/tron/core/services/http/GetAssetIssueListServlet.java +++ b/src/main/java/org/tron/core/services/http/GetAssetIssueListServlet.java @@ -4,6 +4,7 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -20,9 +21,10 @@ public class GetAssetIssueListServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { + boolean visible = Util.getVisible(request); AssetIssueList reply = wallet.getAssetIssueList(); if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply)); + response.getWriter().println(JsonFormat.printToString(reply, visible)); } else { response.getWriter().println("{}"); } diff --git a/src/main/java/org/tron/core/services/http/GetBlockByIdServlet.java b/src/main/java/org/tron/core/services/http/GetBlockByIdServlet.java index a5caff82c75..27f2d6c7e2b 100644 --- a/src/main/java/org/tron/core/services/http/GetBlockByIdServlet.java +++ b/src/main/java/org/tron/core/services/http/GetBlockByIdServlet.java @@ -1,11 +1,13 @@ package org.tron.core.services.http; import com.google.protobuf.ByteString; + import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -14,6 +16,7 @@ import org.tron.core.Wallet; import org.tron.protos.Protocol.Block; + @Component @Slf4j(topic = "API") public class GetBlockByIdServlet extends HttpServlet { @@ -23,10 +26,11 @@ public class GetBlockByIdServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { + boolean visible = Util.getVisible(request); String input = request.getParameter("value"); Block reply = wallet.getBlockById(ByteString.copyFrom(ByteArray.fromHexString(input))); if (reply != null) { - response.getWriter().println(Util.printBlock(reply)); + response.getWriter().println(Util.printBlock(reply, visible)); } else { response.getWriter().println("{}"); } @@ -45,11 +49,12 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String input = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); + boolean visible = Util.getVisiblePost(input); BytesMessage.Builder build = BytesMessage.newBuilder(); - JsonFormat.merge(input, build); + JsonFormat.merge(input, build, visible); Block reply = wallet.getBlockById(build.getValue()); if (reply != null) { - response.getWriter().println(Util.printBlock(reply)); + response.getWriter().println(Util.printBlock(reply, visible)); } else { response.getWriter().println("{}"); } diff --git a/src/main/java/org/tron/core/services/http/GetBlockByLatestNumServlet.java b/src/main/java/org/tron/core/services/http/GetBlockByLatestNumServlet.java index 0ea492d6f27..213f9700668 100644 --- a/src/main/java/org/tron/core/services/http/GetBlockByLatestNumServlet.java +++ b/src/main/java/org/tron/core/services/http/GetBlockByLatestNumServlet.java @@ -5,6 +5,7 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -12,6 +13,7 @@ import org.tron.api.GrpcAPI.NumberMessage; import org.tron.core.Wallet; + @Component @Slf4j(topic = "API") public class GetBlockByLatestNumServlet extends HttpServlet { @@ -22,11 +24,12 @@ public class GetBlockByLatestNumServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { + boolean visible = Util.getVisible(request); long getNum = Long.parseLong(request.getParameter("num")); if (getNum > 0 && getNum < BLOCK_LIMIT_NUM) { BlockList reply = wallet.getBlockByLatestNum(getNum); if (reply != null) { - response.getWriter().println(Util.printBlockList(reply)); + response.getWriter().println(Util.printBlockList(reply, visible)); return; } } @@ -46,13 +49,14 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String input = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); + boolean visible = Util.getVisiblePost(input); NumberMessage.Builder build = NumberMessage.newBuilder(); - JsonFormat.merge(input, build); + JsonFormat.merge(input, build, visible); long getNum = build.getNum(); if (getNum > 0 && getNum < BLOCK_LIMIT_NUM) { BlockList reply = wallet.getBlockByLatestNum(getNum); if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply)); + response.getWriter().println(Util.printBlockList(reply, visible)); return; } } diff --git a/src/main/java/org/tron/core/services/http/GetBlockByLimitNextServlet.java b/src/main/java/org/tron/core/services/http/GetBlockByLimitNextServlet.java index 68c3bdf1fef..d35b0ee2406 100644 --- a/src/main/java/org/tron/core/services/http/GetBlockByLimitNextServlet.java +++ b/src/main/java/org/tron/core/services/http/GetBlockByLimitNextServlet.java @@ -5,6 +5,7 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -12,6 +13,7 @@ import org.tron.api.GrpcAPI.BlockList; import org.tron.core.Wallet; + @Component @Slf4j(topic = "API") public class GetBlockByLimitNextServlet extends HttpServlet { @@ -22,12 +24,13 @@ public class GetBlockByLimitNextServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { + boolean visible = Util.getVisible(request); long startNum = Long.parseLong(request.getParameter("startNum")); long endNum = Long.parseLong(request.getParameter("endNum")); if (endNum > 0 && endNum > startNum && endNum - startNum <= BLOCK_LIMIT_NUM) { BlockList reply = wallet.getBlocksByLimitNext(startNum, endNum - startNum); if (reply != null) { - response.getWriter().println(Util.printBlockList(reply)); + response.getWriter().println(Util.printBlockList(reply, visible)); return; } } @@ -47,14 +50,15 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String input = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); + boolean visible = Util.getVisiblePost(input); BlockLimit.Builder build = BlockLimit.newBuilder(); - JsonFormat.merge(input, build); + JsonFormat.merge(input, build, visible); long startNum = build.getStartNum(); long endNum = build.getEndNum(); if (endNum > 0 && endNum > startNum && endNum - startNum <= BLOCK_LIMIT_NUM) { BlockList reply = wallet.getBlocksByLimitNext(startNum, endNum - startNum); if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply)); + response.getWriter().println(Util.printBlockList(reply, visible)); return; } } diff --git a/src/main/java/org/tron/core/services/http/GetBlockByNumServlet.java b/src/main/java/org/tron/core/services/http/GetBlockByNumServlet.java index c2d77219055..4c8e2d8daec 100644 --- a/src/main/java/org/tron/core/services/http/GetBlockByNumServlet.java +++ b/src/main/java/org/tron/core/services/http/GetBlockByNumServlet.java @@ -5,6 +5,7 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -12,6 +13,7 @@ import org.tron.core.Wallet; import org.tron.protos.Protocol.Block; + @Component @Slf4j(topic = "API") public class GetBlockByNumServlet extends HttpServlet { @@ -21,10 +23,11 @@ public class GetBlockByNumServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { + boolean visible = Util.getVisible(request); long num = Long.parseLong(request.getParameter("num")); Block reply = wallet.getBlockByNum(num); if (reply != null) { - response.getWriter().println(Util.printBlock(reply)); + response.getWriter().println(Util.printBlock(reply, visible)); } else { response.getWriter().println("{}"); } @@ -43,11 +46,12 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String input = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); + boolean visible = Util.getVisiblePost(input); NumberMessage.Builder build = NumberMessage.newBuilder(); - JsonFormat.merge(input, build); + JsonFormat.merge(input, build, visible); Block reply = wallet.getBlockByNum(build.getNum()); if (reply != null) { - response.getWriter().println(Util.printBlock(reply)); + response.getWriter().println(Util.printBlock(reply, visible)); } else { response.getWriter().println("{}"); } diff --git a/src/main/java/org/tron/core/services/http/GetChainParametersServlet.java b/src/main/java/org/tron/core/services/http/GetChainParametersServlet.java index d0c145c68d3..78d4045357a 100644 --- a/src/main/java/org/tron/core/services/http/GetChainParametersServlet.java +++ b/src/main/java/org/tron/core/services/http/GetChainParametersServlet.java @@ -4,6 +4,7 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -19,7 +20,8 @@ public class GetChainParametersServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) { try { - response.getWriter().println(JsonFormat.printToString(wallet.getChainParameters())); + boolean visible = Util.getVisible(request); + response.getWriter().println(JsonFormat.printToString(wallet.getChainParameters(), visible)); } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); try { diff --git a/src/main/java/org/tron/core/services/http/GetContractServlet.java b/src/main/java/org/tron/core/services/http/GetContractServlet.java index d13d15b157d..c3cd8e975cf 100644 --- a/src/main/java/org/tron/core/services/http/GetContractServlet.java +++ b/src/main/java/org/tron/core/services/http/GetContractServlet.java @@ -1,11 +1,13 @@ package org.tron.core.services.http; import com.alibaba.fastjson.JSONObject; + import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -23,14 +25,19 @@ public class GetContractServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { + boolean visible = Util.getVisible(request); String input = request.getParameter("value"); + if (visible) { + input = Util.getHexAddress(input); + } + JSONObject jsonObject = new JSONObject(); jsonObject.put("value", input); BytesMessage.Builder build = BytesMessage.newBuilder(); - JsonFormat.merge(jsonObject.toJSONString(), build); + JsonFormat.merge(jsonObject.toJSONString(), build, visible); SmartContract smartContract = wallet.getContract(build.build()); JSONObject jsonSmartContract = JSONObject - .parseObject(JsonFormat.printToString(smartContract)); + .parseObject(JsonFormat.printToString(smartContract, visible)); response.getWriter().println(jsonSmartContract.toJSONString()); } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); @@ -47,11 +54,19 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String input = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); + boolean visible = Util.getVisiblePost(input); + if (visible) { + JSONObject jsonObject = JSONObject.parseObject(input); + String value = jsonObject.getString("value"); + jsonObject.put("value", Util.getHexAddress(value)); + input = jsonObject.toJSONString(); + } + BytesMessage.Builder build = BytesMessage.newBuilder(); - JsonFormat.merge(input, build); + JsonFormat.merge(input, build, visible); SmartContract smartContract = wallet.getContract(build.build()); JSONObject jsonSmartContract = JSONObject - .parseObject(JsonFormat.printToString(smartContract)); + .parseObject(JsonFormat.printToString(smartContract, visible)); response.getWriter().println(jsonSmartContract.toJSONString()); } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); diff --git a/src/main/java/org/tron/core/services/http/GetDelegatedResourceAccountIndexServlet.java b/src/main/java/org/tron/core/services/http/GetDelegatedResourceAccountIndexServlet.java index 0e6612d02ea..fe763876b13 100644 --- a/src/main/java/org/tron/core/services/http/GetDelegatedResourceAccountIndexServlet.java +++ b/src/main/java/org/tron/core/services/http/GetDelegatedResourceAccountIndexServlet.java @@ -1,11 +1,14 @@ package org.tron.core.services.http; +import com.alibaba.fastjson.JSONObject; import com.google.protobuf.ByteString; + import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -14,6 +17,7 @@ import org.tron.core.Wallet; import org.tron.protos.Protocol.DelegatedResourceAccountIndex; + @Component @Slf4j(topic = "API") public class GetDelegatedResourceAccountIndexServlet extends HttpServlet { @@ -23,12 +27,16 @@ public class GetDelegatedResourceAccountIndexServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { + boolean visible = Util.getVisible(request); String address = request.getParameter("value"); + if (visible) { + address = Util.getHexAddress(address); + } DelegatedResourceAccountIndex reply = wallet.getDelegatedResourceAccountIndex( ByteString.copyFrom(ByteArray.fromHexString(address))); if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply)); + response.getWriter().println(JsonFormat.printToString(reply, visible)); } else { response.getWriter().println("{}"); } @@ -47,12 +55,20 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String input = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); + boolean visible = Util.getVisiblePost(input); + if (visible) { + JSONObject jsonObject = JSONObject.parseObject(input); + String value = jsonObject.getString("value"); + jsonObject.put("value", Util.getHexAddress(value)); + input = jsonObject.toJSONString(); + } + BytesMessage.Builder build = BytesMessage.newBuilder(); - JsonFormat.merge(input, build); + JsonFormat.merge(input, build, visible); DelegatedResourceAccountIndex reply = wallet.getDelegatedResourceAccountIndex(build.getValue()); if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply)); + response.getWriter().println(JsonFormat.printToString(reply, visible)); } else { response.getWriter().println("{}"); } diff --git a/src/main/java/org/tron/core/services/http/GetDelegatedResourceServlet.java b/src/main/java/org/tron/core/services/http/GetDelegatedResourceServlet.java index 36bdb380585..fe4f93ed1a9 100644 --- a/src/main/java/org/tron/core/services/http/GetDelegatedResourceServlet.java +++ b/src/main/java/org/tron/core/services/http/GetDelegatedResourceServlet.java @@ -1,11 +1,13 @@ package org.tron.core.services.http; import com.google.protobuf.ByteString; + import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -14,6 +16,7 @@ import org.tron.common.utils.ByteArray; import org.tron.core.Wallet; + @Component @Slf4j(topic = "API") public class GetDelegatedResourceServlet extends HttpServlet { @@ -23,15 +26,20 @@ public class GetDelegatedResourceServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { + boolean visible = Util.getVisible(request); String fromAddress = request.getParameter("fromAddress"); String toAddress = request.getParameter("toAddress"); + if (visible) { + fromAddress = Util.getHexAddress(fromAddress); + toAddress = Util.getHexAddress(toAddress); + } DelegatedResourceList reply = wallet.getDelegatedResource( ByteString.copyFrom(ByteArray.fromHexString(fromAddress)), ByteString.copyFrom(ByteArray.fromHexString(toAddress))); if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply)); + response.getWriter().println(JsonFormat.printToString(reply, visible)); } else { response.getWriter().println("{}"); } @@ -50,12 +58,13 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String input = request.getReader().lines().collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); + boolean visible = Util.getVisiblePost(input); DelegatedResourceMessage.Builder build = DelegatedResourceMessage.newBuilder(); - JsonFormat.merge(input, build); + JsonFormat.merge(input, build, visible); DelegatedResourceList reply = wallet.getDelegatedResource(build.getFromAddress(), build.getToAddress()); if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply)); + response.getWriter().println(JsonFormat.printToString(reply, visible)); } else { response.getWriter().println("{}"); } diff --git a/src/main/java/org/tron/core/services/http/GetExchangeByIdServlet.java b/src/main/java/org/tron/core/services/http/GetExchangeByIdServlet.java index cb3d7535233..af2f00d391c 100644 --- a/src/main/java/org/tron/core/services/http/GetExchangeByIdServlet.java +++ b/src/main/java/org/tron/core/services/http/GetExchangeByIdServlet.java @@ -3,6 +3,7 @@ import com.alibaba.fastjson.JSONObject; import com.google.protobuf.ByteString; import java.io.IOException; +import java.security.InvalidParameterException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; @@ -26,11 +27,13 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String input = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); + boolean visible = Util.getVisiblePost(input); JSONObject jsonObject = JSONObject.parseObject(input); - long id = jsonObject.getLong("id"); + long id = Util.getJsonLongValue(jsonObject, "id", true); response.getWriter() .println(JsonFormat - .printToString(wallet.getExchangeById(ByteString.copyFrom(ByteArray.fromLong(id))))); + .printToString(wallet.getExchangeById(ByteString.copyFrom(ByteArray.fromLong(id))), + visible)); } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); try { @@ -43,10 +46,12 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { + boolean visible = Util.getVisible(request); String input = request.getParameter("id"); response.getWriter() .println(JsonFormat.printToString(wallet - .getExchangeById(ByteString.copyFrom(ByteArray.fromLong(Long.parseLong(input)))))); + .getExchangeById(ByteString.copyFrom(ByteArray.fromLong(Long.parseLong(input)))), + visible)); } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); try { diff --git a/src/main/java/org/tron/core/services/http/GetNextMaintenanceTimeServlet.java b/src/main/java/org/tron/core/services/http/GetNextMaintenanceTimeServlet.java index fb09c4a82c2..d90622a1514 100644 --- a/src/main/java/org/tron/core/services/http/GetNextMaintenanceTimeServlet.java +++ b/src/main/java/org/tron/core/services/http/GetNextMaintenanceTimeServlet.java @@ -4,12 +4,14 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tron.api.GrpcAPI.NumberMessage; import org.tron.core.Wallet; + @Component @Slf4j(topic = "API") public class GetNextMaintenanceTimeServlet extends HttpServlet { @@ -19,9 +21,10 @@ public class GetNextMaintenanceTimeServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { + boolean visible = Util.getVisible(request); NumberMessage reply = wallet.getNextMaintenanceTime(); if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply)); + response.getWriter().println(JsonFormat.printToString(reply, visible)); } else { response.getWriter().println("{}"); } diff --git a/src/main/java/org/tron/core/services/http/GetNodeInfoServlet.java b/src/main/java/org/tron/core/services/http/GetNodeInfoServlet.java index 15c1b4852ad..b3cd2c70fe8 100644 --- a/src/main/java/org/tron/core/services/http/GetNodeInfoServlet.java +++ b/src/main/java/org/tron/core/services/http/GetNodeInfoServlet.java @@ -1,10 +1,12 @@ package org.tron.core.services.http; import com.alibaba.fastjson.JSON; + import java.io.IOException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; diff --git a/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java b/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java index 530d78463c3..a754f14372e 100644 --- a/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java +++ b/src/main/java/org/tron/core/services/http/GetNowBlockServlet.java @@ -4,6 +4,7 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -20,9 +21,10 @@ public class GetNowBlockServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { + boolean visible = Util.getVisible(request); Block reply = wallet.getNowBlock(); if (reply != null) { - response.getWriter().println(Util.printBlock(reply)); + response.getWriter().println(Util.printBlock(reply, visible)); } else { response.getWriter().println("{}"); } diff --git a/src/main/java/org/tron/core/services/http/GetPaginatedAssetIssueListServlet.java b/src/main/java/org/tron/core/services/http/GetPaginatedAssetIssueListServlet.java index c78ff7aa597..9b7b3a9c2cd 100644 --- a/src/main/java/org/tron/core/services/http/GetPaginatedAssetIssueListServlet.java +++ b/src/main/java/org/tron/core/services/http/GetPaginatedAssetIssueListServlet.java @@ -5,6 +5,7 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -29,11 +30,12 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String input = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); + boolean visible = Util.getVisiblePost(input); PaginatedMessage.Builder build = PaginatedMessage.newBuilder(); - JsonFormat.merge(input, build); + JsonFormat.merge(input, build, visible); AssetIssueList reply = wallet.getAssetIssueList(build.getOffset(), build.getLimit()); if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply)); + response.getWriter().println(JsonFormat.printToString(reply, visible)); } else { response.getWriter().println("{}"); } diff --git a/src/main/java/org/tron/core/services/http/GetPaginatedExchangeListServlet.java b/src/main/java/org/tron/core/services/http/GetPaginatedExchangeListServlet.java index 53ecf527a30..07907127844 100644 --- a/src/main/java/org/tron/core/services/http/GetPaginatedExchangeListServlet.java +++ b/src/main/java/org/tron/core/services/http/GetPaginatedExchangeListServlet.java @@ -5,6 +5,7 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -29,11 +30,12 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String input = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); + boolean visible = Util.getVisiblePost(input); PaginatedMessage.Builder build = PaginatedMessage.newBuilder(); - JsonFormat.merge(input, build); + JsonFormat.merge(input, build, visible); ExchangeList reply = wallet.getPaginatedExchangeList(build.getOffset(), build.getLimit()); if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply)); + response.getWriter().println(JsonFormat.printToString(reply, visible)); } else { response.getWriter().println("{}"); } diff --git a/src/main/java/org/tron/core/services/http/GetPaginatedProposalListServlet.java b/src/main/java/org/tron/core/services/http/GetPaginatedProposalListServlet.java index 113f42d765c..b566ac3475f 100644 --- a/src/main/java/org/tron/core/services/http/GetPaginatedProposalListServlet.java +++ b/src/main/java/org/tron/core/services/http/GetPaginatedProposalListServlet.java @@ -5,6 +5,7 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -29,11 +30,12 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String input = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); + boolean visible = Util.getVisiblePost(input); PaginatedMessage.Builder build = PaginatedMessage.newBuilder(); - JsonFormat.merge(input, build); + JsonFormat.merge(input, build, visible); ProposalList reply = wallet.getPaginatedProposalList(build.getOffset(), build.getLimit()); if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply)); + response.getWriter().println(JsonFormat.printToString(reply, visible)); } else { response.getWriter().println("{}"); } diff --git a/src/main/java/org/tron/core/services/http/GetProposalByIdServlet.java b/src/main/java/org/tron/core/services/http/GetProposalByIdServlet.java index 27167ef22f1..d475e6843a2 100644 --- a/src/main/java/org/tron/core/services/http/GetProposalByIdServlet.java +++ b/src/main/java/org/tron/core/services/http/GetProposalByIdServlet.java @@ -3,6 +3,7 @@ import com.alibaba.fastjson.JSONObject; import com.google.protobuf.ByteString; import java.io.IOException; +import java.security.InvalidParameterException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; @@ -14,6 +15,7 @@ import org.tron.core.Wallet; import org.tron.protos.Protocol.Proposal; + @Component @Slf4j(topic = "API") public class GetProposalByIdServlet extends HttpServlet { @@ -23,11 +25,12 @@ public class GetProposalByIdServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { + boolean visible = Util.getVisible(request); String input = request.getParameter("id"); long id = new Long(input); Proposal reply = wallet.getProposalById(ByteString.copyFrom(ByteArray.fromLong(id))); if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply)); + response.getWriter().println(JsonFormat.printToString(reply, visible)); } else { response.getWriter().println("{}"); } @@ -46,11 +49,12 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String input = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); + boolean visible = Util.getVisiblePost(input); JSONObject jsonObject = JSONObject.parseObject(input); - long id = jsonObject.getLong("id"); + long id = Util.getJsonLongValue(jsonObject, "id", true); Proposal reply = wallet.getProposalById(ByteString.copyFrom(ByteArray.fromLong(id))); if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply)); + response.getWriter().println(JsonFormat.printToString(reply, visible)); } else { response.getWriter().println("{}"); } diff --git a/src/main/java/org/tron/core/services/http/GetTransactionApprovedListServlet.java b/src/main/java/org/tron/core/services/http/GetTransactionApprovedListServlet.java index aba6297d77a..612583364f1 100644 --- a/src/main/java/org/tron/core/services/http/GetTransactionApprovedListServlet.java +++ b/src/main/java/org/tron/core/services/http/GetTransactionApprovedListServlet.java @@ -5,6 +5,7 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -29,10 +30,11 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String input = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); - Transaction transaction = Util.packTransaction(input); + boolean visible = Util.getVisiblePost(input); + Transaction transaction = Util.packTransaction(input, visible); TransactionApprovedList reply = wallet.getTransactionApprovedList(transaction); if (reply != null) { - response.getWriter().println(Util.printTransactionApprovedList(reply)); + response.getWriter().println(Util.printTransactionApprovedList(reply, visible)); } else { response.getWriter().println("{}"); } diff --git a/src/main/java/org/tron/core/services/http/GetTransactionByIdServlet.java b/src/main/java/org/tron/core/services/http/GetTransactionByIdServlet.java index 1a1c688b96b..28bc6bccb10 100644 --- a/src/main/java/org/tron/core/services/http/GetTransactionByIdServlet.java +++ b/src/main/java/org/tron/core/services/http/GetTransactionByIdServlet.java @@ -1,11 +1,13 @@ package org.tron.core.services.http; import com.google.protobuf.ByteString; + import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -14,6 +16,7 @@ import org.tron.core.Wallet; import org.tron.protos.Protocol.Transaction; + @Component @Slf4j(topic = "API") public class GetTransactionByIdServlet extends HttpServlet { @@ -23,11 +26,12 @@ public class GetTransactionByIdServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { + boolean visible = Util.getVisible(request); String input = request.getParameter("value"); Transaction reply = wallet .getTransactionById(ByteString.copyFrom(ByteArray.fromHexString(input))); if (reply != null) { - response.getWriter().println(Util.printTransaction(reply)); + response.getWriter().println(Util.printTransaction(reply, visible)); } else { response.getWriter().println("{}"); } @@ -46,11 +50,12 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String input = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); + boolean visible = Util.getVisiblePost(input); BytesMessage.Builder build = BytesMessage.newBuilder(); - JsonFormat.merge(input, build); + JsonFormat.merge(input, build, visible); Transaction reply = wallet.getTransactionById(build.getValue()); if (reply != null) { - response.getWriter().println(Util.printTransaction(reply)); + response.getWriter().println(Util.printTransaction(reply, visible)); } else { response.getWriter().println("{}"); } diff --git a/src/main/java/org/tron/core/services/http/GetTransactionCountByBlockNumServlet.java b/src/main/java/org/tron/core/services/http/GetTransactionCountByBlockNumServlet.java index ae5e3db8d10..1b58f1d9aa7 100644 --- a/src/main/java/org/tron/core/services/http/GetTransactionCountByBlockNumServlet.java +++ b/src/main/java/org/tron/core/services/http/GetTransactionCountByBlockNumServlet.java @@ -5,12 +5,14 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tron.api.GrpcAPI.NumberMessage; import org.tron.core.Wallet; + @Component @Slf4j(topic = "API") public class GetTransactionCountByBlockNumServlet extends HttpServlet { @@ -38,8 +40,9 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String input = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); + boolean visible = Util.getVisiblePost(input); NumberMessage.Builder build = NumberMessage.newBuilder(); - JsonFormat.merge(input, build); + JsonFormat.merge(input, build, visible); long count = wallet.getTransactionCountByBlockNum(build.getNum()); response.getWriter().println("{\"count\": " + count + "}"); } catch (Exception e) { diff --git a/src/main/java/org/tron/core/services/http/GetTransactionInfoByIdServlet.java b/src/main/java/org/tron/core/services/http/GetTransactionInfoByIdServlet.java index 8148e0cc068..7ae713a2688 100644 --- a/src/main/java/org/tron/core/services/http/GetTransactionInfoByIdServlet.java +++ b/src/main/java/org/tron/core/services/http/GetTransactionInfoByIdServlet.java @@ -1,11 +1,13 @@ package org.tron.core.services.http; import com.google.protobuf.ByteString; + import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -14,6 +16,7 @@ import org.tron.core.Wallet; import org.tron.protos.Protocol.TransactionInfo; + @Component @Slf4j(topic = "API") public class GetTransactionInfoByIdServlet extends HttpServlet { @@ -23,11 +26,12 @@ public class GetTransactionInfoByIdServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { + boolean visible = Util.getVisible(request); String input = request.getParameter("value"); TransactionInfo reply = wallet .getTransactionInfoById(ByteString.copyFrom(ByteArray.fromHexString(input))); if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply)); + response.getWriter().println(JsonFormat.printToString(reply, visible)); } else { response.getWriter().println("{}"); } @@ -46,11 +50,12 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String input = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); + boolean visible = Util.getVisiblePost(input); BytesMessage.Builder build = BytesMessage.newBuilder(); - JsonFormat.merge(input, build); + JsonFormat.merge(input, build, visible); TransactionInfo reply = wallet.getTransactionInfoById(build.getValue()); if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply)); + response.getWriter().println(JsonFormat.printToString(reply, visible)); } else { response.getWriter().println("{}"); } diff --git a/src/main/java/org/tron/core/services/http/GetTransactionSignWeightServlet.java b/src/main/java/org/tron/core/services/http/GetTransactionSignWeightServlet.java index 80ae69f7960..23c645e5ea4 100644 --- a/src/main/java/org/tron/core/services/http/GetTransactionSignWeightServlet.java +++ b/src/main/java/org/tron/core/services/http/GetTransactionSignWeightServlet.java @@ -5,6 +5,7 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -29,10 +30,11 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String input = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); - Transaction transaction = Util.packTransaction(input); + boolean visible = Util.getVisiblePost(input); + Transaction transaction = Util.packTransaction(input, visible); TransactionSignWeight reply = wallet.getTransactionSignWeight(transaction); if (reply != null) { - response.getWriter().println(Util.printTransactionSignWeight(reply)); + response.getWriter().println(Util.printTransactionSignWeight(reply, visible)); } else { response.getWriter().println("{}"); } diff --git a/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java b/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java new file mode 100644 index 00000000000..1242f42d660 --- /dev/null +++ b/src/main/java/org/tron/core/services/http/HttpSelfFormatFieldName.java @@ -0,0 +1,216 @@ +package org.tron.core.services.http; + +import java.util.HashMap; +import java.util.Map; + +public class HttpSelfFormatFieldName { + private static Map AddressFieldNameMap = new HashMap<>(); + private static Map NameFieldNameMap = new HashMap<>(); + + static { + //***** api.proto ***** + //DelegatedResourceMessage + AddressFieldNameMap.put("protocol.DelegatedResourceMessage.fromAddress", 1); + AddressFieldNameMap.put("protocol.DelegatedResourceMessage.toAddress", 1); + //EasyTransferMessage + AddressFieldNameMap.put("protocol.EasyTransferMessage.toAddress", 1); + //EasyTransferAssetMessage + AddressFieldNameMap.put("protocol.EasyTransferAssetMessage.toAddress", 1); + //EasyTransferByPrivateMessage + AddressFieldNameMap.put("protocol.EasyTransferByPrivateMessage.toAddress", 1); + //EasyTransferAssetByPrivateMessage + AddressFieldNameMap.put("protocol.EasyTransferAssetByPrivateMessage.toAddress", 1); + //TransactionSignWeight + AddressFieldNameMap.put("protocol.TransactionSignWeight.approved_list", 1); + //TransactionApprovedList + AddressFieldNameMap.put("protocol.TransactionApprovedList.approved_list", 1); + + //***** Contract.proto ***** + //AccountCreateContract + AddressFieldNameMap.put("protocol.AccountCreateContract.owner_address", 1); + AddressFieldNameMap.put("protocol.AccountCreateContract.account_address", 1); + //AccountUpdateContract + AddressFieldNameMap.put("protocol.AccountUpdateContract.owner_address", 1); + //SetAccountIdContract + AddressFieldNameMap.put("protocol.SetAccountIdContract.owner_address", 1); + //TransferContract + AddressFieldNameMap.put("protocol.TransferContract.owner_address", 1); + AddressFieldNameMap.put("protocol.TransferContract.to_address", 1); + //CancelDeferredTransactionContract + AddressFieldNameMap.put("protocol.CancelDeferredTransactionContract.ownerAddress", 1); + //TransferAssetContract + AddressFieldNameMap.put("protocol.TransferAssetContract.owner_address", 1); + AddressFieldNameMap.put("protocol.TransferAssetContract.to_address", 1); + //VoteAssetContract + AddressFieldNameMap.put("protocol.VoteAssetContract.owner_address", 1); + AddressFieldNameMap.put("protocol.VoteAssetContract.vote_address", 1); + //VoteWitnessContract + AddressFieldNameMap.put("protocol.VoteWitnessContract.Vote.vote_address", 1); + AddressFieldNameMap.put("protocol.VoteWitnessContract.owner_address", 1); + //UpdateSettingContract + AddressFieldNameMap.put("protocol.UpdateSettingContract.owner_address", 1); + AddressFieldNameMap.put("protocol.UpdateSettingContract.contract_address", 1); + //UpdateEnergyLimitContract + AddressFieldNameMap.put("protocol.UpdateEnergyLimitContract.owner_address", 1); + AddressFieldNameMap.put("protocol.UpdateEnergyLimitContract.contract_address", 1); + //ClearABIContract + AddressFieldNameMap.put("protocol.ClearABIContract.owner_address", 1); + AddressFieldNameMap.put("protocol.ClearABIContract.contract_address", 1); + //WitnessCreateContract + AddressFieldNameMap.put("protocol.WitnessCreateContract.owner_address", 1); + //WitnessUpdateContract + AddressFieldNameMap.put("protocol.WitnessUpdateContract.owner_address", 1); + //AssetIssueContract + AddressFieldNameMap.put("protocol.AssetIssueContract.owner_address", 1); + //ParticipateAssetIssueContract + AddressFieldNameMap.put("protocol.ParticipateAssetIssueContract.owner_address", 1); + AddressFieldNameMap.put("protocol.ParticipateAssetIssueContract.to_address", 1); + //FreezeBalanceContract + AddressFieldNameMap.put("protocol.FreezeBalanceContract.owner_address", 1); + AddressFieldNameMap.put("protocol.FreezeBalanceContract.receiver_address", 1); + //UnfreezeBalanceContract + AddressFieldNameMap.put("protocol.UnfreezeBalanceContract.owner_address", 1); + AddressFieldNameMap.put("protocol.UnfreezeBalanceContract.receiver_address", 1); + //UnfreezeAssetContract + AddressFieldNameMap.put("protocol.UnfreezeAssetContract.owner_address", 1); + //WithdrawBalanceContract + AddressFieldNameMap.put("protocol.WithdrawBalanceContract.owner_address", 1); + //UpdateAssetContract + AddressFieldNameMap.put("protocol.UpdateAssetContract.owner_address", 1); + //ProposalCreateContract + AddressFieldNameMap.put("protocol.ProposalCreateContract.owner_address", 1); + //ProposalApproveContract + AddressFieldNameMap.put("protocol.ProposalApproveContract.owner_address", 1); + //ProposalDeleteContract + AddressFieldNameMap.put("protocol.ProposalDeleteContract.owner_address", 1); + //CreateSmartContract + AddressFieldNameMap.put("protocol.CreateSmartContract.owner_address", 1); + //TriggerSmartContract + AddressFieldNameMap.put("protocol.TriggerSmartContract.owner_address", 1); + AddressFieldNameMap.put("protocol.TriggerSmartContract.contract_address", 1); + //BuyStorageContract + AddressFieldNameMap.put("protocol.BuyStorageContract.owner_address", 1); + //BuyStorageBytesContract + AddressFieldNameMap.put("protocol.BuyStorageBytesContract.owner_address", 1); + //SellStorageContract + AddressFieldNameMap.put("protocol.SellStorageContract.owner_address", 1); + //ExchangeCreateContract + AddressFieldNameMap.put("protocol.ExchangeCreateContract.owner_address", 1); + //ExchangeInjectContract + AddressFieldNameMap.put("protocol.ExchangeInjectContract.owner_address", 1); + //ExchangeWithdrawContract + AddressFieldNameMap.put("protocol.ExchangeWithdrawContract.owner_address", 1); + //ExchangeTransactionContract + AddressFieldNameMap.put("protocol.ExchangeTransactionContract.owner_address", 1); + //AccountPermissionUpdateContract + AddressFieldNameMap.put("protocol.AccountPermissionUpdateContract.owner_address", 1); + + //***** Tron.proto ***** + //AccountId + AddressFieldNameMap.put("protocol.AccountId.address", 1); + //Vote + AddressFieldNameMap.put("protocol.Vote.vote_address", 1); + //Proposal + AddressFieldNameMap.put("protocol.Proposal.proposer_address", 1); + AddressFieldNameMap.put("protocol.Proposal.approvals", 1); + //Exchange + AddressFieldNameMap.put("protocol.Exchange.creator_address", 1); + //Account + AddressFieldNameMap.put("protocol.Account.address", 1); + //Key + AddressFieldNameMap.put("protocol.Key.address", 1); + //DelegatedResource + AddressFieldNameMap.put("protocol.DelegatedResource.from", 1); + AddressFieldNameMap.put("protocol.DelegatedResource.to", 1); + //Witness + AddressFieldNameMap.put("protocol.Witness.address", 1); + //Votes + AddressFieldNameMap.put("protocol.Votes.address", 1); + //TransactionInfo + AddressFieldNameMap.put("protocol.TransactionInfo.Log.address", 1); + AddressFieldNameMap.put("protocol.TransactionInfo.contract_address", 1); + //DeferredTransaction + AddressFieldNameMap.put("protocol.DeferredTransaction.senderAddress", 1); + AddressFieldNameMap.put("protocol.DeferredTransaction.receiverAddress", 1); + //BlockHeader + AddressFieldNameMap.put("protocol.BlockHeader.raw.witness_address", 1); + //SmartContract + AddressFieldNameMap.put("protocol.SmartContract.origin_address", 1); + AddressFieldNameMap.put("protocol.SmartContract.contract_address", 1); + //InternalTransaction + AddressFieldNameMap.put("protocol.InternalTransaction.caller_address", 1); + AddressFieldNameMap.put("protocol.InternalTransaction.transferTo_address", 1); + //DelegatedResourceAccountIndex + AddressFieldNameMap.put("protocol.DelegatedResourceAccountIndex.account", 1); + AddressFieldNameMap.put("protocol.DelegatedResourceAccountIndex.fromAccounts", 1); + AddressFieldNameMap.put("protocol.DelegatedResourceAccountIndex.toAccounts", 1); + + + //***** api.proto ***** + //Return + NameFieldNameMap.put("protocol.Return.message", 1); + //Address + NameFieldNameMap.put("protocol.Address.host", 1); + //EasyTransferMessage + NameFieldNameMap.put("protocol.EasyTransferMessage.passPhrase", 1); + //EasyTransferAssetMessage + NameFieldNameMap.put("protocol.EasyTransferAssetMessage.passPhrase", 1); + + //***** Contract.proto ***** + //AccountUpdateContract + NameFieldNameMap.put("protocol.AccountUpdateContract.account_name", 1); + //SetAccountIdContract + NameFieldNameMap.put("protocol.SetAccountIdContract.account_id", 1); + //TransferAssetContract + NameFieldNameMap.put("protocol.TransferAssetContract.asset_name", 1); + //WitnessCreateContract + NameFieldNameMap.put("protocol.WitnessCreateContract.url", 1); + //WitnessUpdateContract + NameFieldNameMap.put("protocol.WitnessUpdateContract.update_url", 1); + //AssetIssueContract + NameFieldNameMap.put("protocol.AssetIssueContract.name", 1); + NameFieldNameMap.put("protocol.AssetIssueContract.abbr", 1); + NameFieldNameMap.put("protocol.AssetIssueContract.description", 1); + NameFieldNameMap.put("protocol.AssetIssueContract.url", 1); + //ParticipateAssetIssueContract + NameFieldNameMap.put("protocol.ParticipateAssetIssueContract.asset_name", 1); + //UpdateAssetContract + NameFieldNameMap.put("protocol.UpdateAssetContract.description", 1); + NameFieldNameMap.put("protocol.UpdateAssetContract.url", 1); + //ExchangeCreateContract + NameFieldNameMap.put("protocol.ExchangeCreateContract.first_token_id", 1); + NameFieldNameMap.put("protocol.ExchangeCreateContract.second_token_id", 1); + //ExchangeInjectContract + NameFieldNameMap.put("protocol.ExchangeInjectContract.token_id", 1); + //ExchangeWithdrawContract + NameFieldNameMap.put("protocol.ExchangeWithdrawContract.token_id", 1); + //ExchangeTransactionContract + NameFieldNameMap.put("protocol.ExchangeTransactionContract.token_id", 1); + + //***** Tron.proto ***** + //AccountId + NameFieldNameMap.put("protocol.AccountId.name", 1); + //Exchange + NameFieldNameMap.put("protocol.Exchange.first_token_id", 1); + NameFieldNameMap.put("protocol.Exchange.second_token_id", 1); + //Account + NameFieldNameMap.put("protocol.Account.account_name", 1); + NameFieldNameMap.put("protocol.Account.asset_issued_name", 1); + NameFieldNameMap.put("protocol.Account.asset_issued_ID", 1); + NameFieldNameMap.put("protocol.Account.account_id", 1); + //authority + NameFieldNameMap.put("protocol.authority.permission_name", 1); + //Transaction + NameFieldNameMap.put("protocol.Transaction.Contract.ContractName", 1); + //TransactionInfo + NameFieldNameMap.put("protocol.TransactionInfo.resMessage", 1); + } + + public static boolean isAddressFormat(final String name) { + return AddressFieldNameMap.containsKey(name); + } + + public static boolean isNameStringFormat(final String name) { + return NameFieldNameMap.containsKey(name); + } +} diff --git a/src/main/java/org/tron/core/services/http/JsonFormat.java b/src/main/java/org/tron/core/services/http/JsonFormat.java index d7e6d1fbfc9..005db53dd17 100644 --- a/src/main/java/org/tron/core/services/http/JsonFormat.java +++ b/src/main/java/org/tron/core/services/http/JsonFormat.java @@ -38,6 +38,7 @@ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.Message; import com.google.protobuf.UnknownFieldSet; + import java.io.IOException; import java.math.BigInteger; import java.nio.CharBuffer; @@ -49,8 +50,10 @@ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; + import org.apache.commons.lang3.StringUtils; import org.tron.common.utils.ByteArray; +import org.tron.core.Wallet; /** @@ -76,28 +79,31 @@ public class JsonFormat { * (This representation is the new version of the classic "ProtocolPrinter" output from the * original Protocol Buffer system) */ - public static void print(Message message, Appendable output) throws IOException { + public static void print(Message message, Appendable output, boolean selfType) + throws IOException { JsonGenerator generator = new JsonGenerator(output); generator.print("{"); - print(message, generator); + print(message, generator, selfType); generator.print("}"); } /** * Outputs a textual representation of {@code fields} to {@code output}. */ - public static void print(UnknownFieldSet fields, Appendable output) throws IOException { + public static void print(UnknownFieldSet fields, Appendable output, boolean selfType) + throws IOException { JsonGenerator generator = new JsonGenerator(output); generator.print("{"); - printUnknownFields(fields, generator); + printUnknownFields(fields, generator, selfType); generator.print("}"); } - protected static void print(Message message, JsonGenerator generator) throws IOException { + protected static void print(Message message, JsonGenerator generator, boolean selfType) + throws IOException { for (Iterator> iter = message.getAllFields().entrySet() .iterator(); iter.hasNext(); ) { Map.Entry field = iter.next(); - printField(field.getKey(), field.getValue(), generator); + printField(field.getKey(), field.getValue(), generator, selfType); if (iter.hasNext()) { generator.print(","); } @@ -105,16 +111,16 @@ protected static void print(Message message, JsonGenerator generator) throws IOE if (message.getUnknownFields().asMap().size() > 0) { generator.print(", "); } - printUnknownFields(message.getUnknownFields(), generator); + printUnknownFields(message.getUnknownFields(), generator, selfType); } /** * Like {@code print()}, but writes directly to a {@code String} and returns it. */ - public static String printToString(Message message) { + public static String printToString(Message message, boolean selfType) { try { StringBuilder text = new StringBuilder(); - print(message, text); + print(message, text, selfType); return text.toString(); } catch (IOException e) { throw new RuntimeException( @@ -126,10 +132,10 @@ public static String printToString(Message message) { /** * Like {@code print()}, but writes directly to a {@code String} and returns it. */ - public static String printToString(UnknownFieldSet fields) { + public static String printToString(UnknownFieldSet fields, boolean selfType) { try { StringBuilder text = new StringBuilder(); - print(fields, text); + print(fields, text, selfType); return text.toString(); } catch (IOException e) { throw new RuntimeException( @@ -149,15 +155,15 @@ public static String printErrorMsg(Exception ex) { return text.toString(); } - public static void printField(FieldDescriptor field, Object value, JsonGenerator generator) + public static void printField(FieldDescriptor field, Object value, JsonGenerator generator, + boolean selfType) throws IOException { - printSingleField(field, value, generator); + printSingleField(field, value, generator, selfType); } private static void printSingleField(FieldDescriptor field, - Object value, - JsonGenerator generator) throws IOException { + Object value, JsonGenerator generator, boolean selfType) throws IOException { if (field.isExtension()) { generator.print("\""); // We special-case MessageSet elements for compatibility with proto1. @@ -194,21 +200,22 @@ private static void printSingleField(FieldDescriptor field, // Repeated field. Print each element. generator.print("["); for (Iterator iter = ((List) value).iterator(); iter.hasNext(); ) { - printFieldValue(field, iter.next(), generator); + printFieldValue(field, iter.next(), generator, selfType); if (iter.hasNext()) { generator.print(","); } } generator.print("]"); } else { - printFieldValue(field, value, generator); + printFieldValue(field, value, generator, selfType); if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { generator.outdent(); } } } - private static void printFieldValue(FieldDescriptor field, Object value, JsonGenerator generator) + private static void printFieldValue(FieldDescriptor field, Object value, + JsonGenerator generator, boolean selfType) throws IOException { switch (field.getType()) { case INT32: @@ -242,7 +249,7 @@ private static void printFieldValue(FieldDescriptor field, Object value, JsonGen case BYTES: { generator.print("\""); - generator.print(escapeBytes((ByteString) value)); + generator.print(escapeBytes((ByteString) value, field.getFullName(), selfType)); generator.print("\""); break; } @@ -257,15 +264,15 @@ private static void printFieldValue(FieldDescriptor field, Object value, JsonGen case MESSAGE: case GROUP: generator.print("{"); - print((Message) value, generator); + print((Message) value, generator, selfType); generator.print("}"); break; default: } } - protected static void printUnknownFields(UnknownFieldSet unknownFields, JsonGenerator generator) - throws IOException { + protected static void printUnknownFields(UnknownFieldSet unknownFields, JsonGenerator generator, + boolean selfType) throws IOException { boolean firstField = true; for (Map.Entry entry : unknownFields.asMap().entrySet()) { final UnknownFieldSet.Field field = entry.getValue(); @@ -312,7 +319,7 @@ protected static void printUnknownFields(UnknownFieldSet unknownFields, JsonGene generator.print(", "); } generator.print("\""); - generator.print(escapeBytes(value)); + generator.print(escapeBytes(value, "Hex", selfType)); //Just to HEX generator.print("\""); } for (UnknownFieldSet value : field.getGroupList()) { @@ -322,7 +329,7 @@ protected static void printUnknownFields(UnknownFieldSet unknownFields, JsonGene generator.print(", "); } generator.print("{"); - printUnknownFields(value, generator); + printUnknownFields(value, generator, selfType); generator.print("}"); } generator.print("]"); @@ -359,15 +366,17 @@ private static String unsignedToString(long value) { /** * Parse a text-format message from {@code input} and merge the contents into {@code builder}. */ - public static void merge(Readable input, Message.Builder builder) throws IOException { - merge(input, ExtensionRegistry.getEmptyRegistry(), builder); + public static void merge(Readable input, Message.Builder builder, boolean selfType) + throws IOException { + merge(input, ExtensionRegistry.getEmptyRegistry(), builder, selfType); } /** * Parse a text-format message from {@code input} and merge the contents into {@code builder}. */ - public static void merge(CharSequence input, Message.Builder builder) throws ParseException { - merge(input, ExtensionRegistry.getEmptyRegistry(), builder); + public static void merge(CharSequence input, Message.Builder builder, boolean selfType) + throws ParseException { + merge(input, ExtensionRegistry.getEmptyRegistry(), builder, selfType); } /** @@ -376,7 +385,7 @@ public static void merge(CharSequence input, Message.Builder builder) throws Par */ public static void merge(Readable input, ExtensionRegistry extensionRegistry, - Message.Builder builder) throws IOException { + Message.Builder builder, boolean selfType) throws IOException { // Read the entire input to a String then parse that. // If StreamTokenizer were not quite so crippled, or if there were a kind @@ -385,7 +394,7 @@ public static void merge(Readable input, // we would not have to read to one big String. Alas, none of these is // the case. Oh well. - merge(toStringBuilder(input), extensionRegistry, builder); + merge(toStringBuilder(input), extensionRegistry, builder, selfType); } /** @@ -394,14 +403,14 @@ public static void merge(Readable input, */ public static void merge(CharSequence input, ExtensionRegistry extensionRegistry, - Message.Builder builder) throws ParseException { + Message.Builder builder, boolean selfType) throws ParseException { Tokenizer tokenizer = new Tokenizer(input); // Based on the state machine @ http://json.org/ tokenizer.consume("{"); // Needs to happen when the object starts. while (!tokenizer.tryConsume("}")) { // Continue till the object is done - mergeField(tokenizer, extensionRegistry, builder); + mergeField(tokenizer, extensionRegistry, builder, selfType); } // Test to make sure the tokenizer has reached the end of the stream. if (!tokenizer.atEnd()) { @@ -432,8 +441,8 @@ protected static StringBuilder toStringBuilder(Readable input) throws IOExceptio * detected after the field ends, the next field will be parsed automatically */ protected static void mergeField(Tokenizer tokenizer, - ExtensionRegistry extensionRegistry, - Message.Builder builder) throws ParseException { + ExtensionRegistry extensionRegistry, Message.Builder builder, + boolean selfType) throws ParseException { FieldDescriptor field; Descriptor type = builder.getDescriptorForType(); final ExtensionRegistry.ExtensionInfo extension; @@ -493,17 +502,17 @@ protected static void mergeField(Tokenizer tokenizer, if (array) { while (!tokenizer.tryConsume("]")) { - handleValue(tokenizer, extensionRegistry, builder, field, extension, unknown); + handleValue(tokenizer, extensionRegistry, builder, field, extension, unknown, selfType); tokenizer.tryConsume(","); } } else { - handleValue(tokenizer, extensionRegistry, builder, field, extension, unknown); + handleValue(tokenizer, extensionRegistry, builder, field, extension, unknown, selfType); } } if (tokenizer.tryConsume(",")) { // Continue with the next field - mergeField(tokenizer, extensionRegistry, builder); + mergeField(tokenizer, extensionRegistry, builder, selfType); } } @@ -545,13 +554,14 @@ private static void handleValue(Tokenizer tokenizer, Message.Builder builder, FieldDescriptor field, ExtensionRegistry.ExtensionInfo extension, - boolean unknown) throws ParseException { + boolean unknown, boolean selfType) throws ParseException { Object value = null; if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { - value = handleObject(tokenizer, extensionRegistry, builder, field, extension, unknown); + value = handleObject(tokenizer, extensionRegistry, builder, field, extension, unknown, + selfType); } else { - value = handlePrimitive(tokenizer, field); + value = handlePrimitive(tokenizer, field, selfType); } if (value != null) { if (field.isRepeated()) { @@ -562,7 +572,8 @@ private static void handleValue(Tokenizer tokenizer, } } - private static Object handlePrimitive(Tokenizer tokenizer, FieldDescriptor field) + private static Object handlePrimitive(Tokenizer tokenizer, FieldDescriptor field, + boolean selfType) throws ParseException { Object value = null; if ("null".equals(tokenizer.currentToken())) { @@ -609,7 +620,7 @@ private static Object handlePrimitive(Tokenizer tokenizer, FieldDescriptor field break; case BYTES: - value = tokenizer.consumeByteString(); + value = tokenizer.consumeByteString(field.getFullName(), selfType); break; case ENUM: { @@ -657,7 +668,7 @@ private static Object handleObject(Tokenizer tokenizer, Message.Builder builder, FieldDescriptor field, ExtensionRegistry.ExtensionInfo extension, - boolean unknown) throws ParseException { + boolean unknown, boolean selfType) throws ParseException { Message.Builder subBuilder; if (extension == null) { @@ -667,7 +678,7 @@ private static Object handleObject(Tokenizer tokenizer, } if (unknown) { - ByteString data = tokenizer.consumeByteString(); + ByteString data = tokenizer.consumeByteString("", selfType); try { subBuilder.mergeFrom(data); return subBuilder.build(); @@ -683,7 +694,7 @@ private static Object handleObject(Tokenizer tokenizer, if (tokenizer.atEnd()) { throw tokenizer.parseException("Expected \"" + endToken + "\"."); } - mergeField(tokenizer, extensionRegistry, subBuilder); + mergeField(tokenizer, extensionRegistry, subBuilder, selfType); if (tokenizer.tryConsume(",")) { // there are more fields in the object, so continue continue; @@ -704,6 +715,29 @@ static String escapeBytes(ByteString input) { return ByteArray.toHexString(input.toByteArray()); } + static String escapeBytes(ByteString input, final String fliedName, boolean selfType) { + if (!selfType) { + return ByteArray.toHexString(input.toByteArray()); + } else { + return escapeBytesSelfType(input, fliedName); + } + } + + static String escapeBytesSelfType(ByteString input, final String fliedName) { + //Address + if (HttpSelfFormatFieldName.isAddressFormat(fliedName)) { + return Wallet.encode58Check(input.toByteArray()); + } + + //Normal String + if (HttpSelfFormatFieldName.isNameStringFormat(fliedName)) { + return new String(input.toByteArray()); + } + + //HEX + return ByteArray.toHexString(input.toByteArray()); + } + static String unicodeEscaped(char ch) { if (ch < 0x10) { return "\\u000" + Integer.toHexString(ch); @@ -862,14 +896,14 @@ static String unescapeText(String input) throws InvalidEscapeSequence { } /** - * Is this an octal digit? + * Is this an octal digit. */ private static boolean isOctal(char c) { return ('0' <= c) && (c <= '7'); } /** - * Is this a hex digit? + * Is this a hex digit. */ private static boolean isHex(char c) { return (('0' <= c) && (c <= '9')) || (('a' <= c) && (c <= 'f')) @@ -1144,7 +1178,7 @@ public Tokenizer(CharSequence text) { } /** - * Are we at the end of the input? + * Are we at the end of the input. */ public boolean atEnd() { return currentToken.length() == 0; @@ -1304,7 +1338,7 @@ static ByteString unescapeBytes(CharSequence input) throws InvalidEscapeSequence // ++i; // code = digitValue(input.charAt(i)); // } else { -// throw new InvalidEscapeSequence("Invalid escape sequence: '\\x' with no digits"); +// throw new InvalidEscapeSequence("Invalid escape sequence: '\\x' with no digits"); // } // if ((i + 1 < input.length()) && isHex(input.charAt(i + 1))) { // ++i; @@ -1334,7 +1368,6 @@ static ByteString unescapeBytes(CharSequence input) throws InvalidEscapeSequence // result[pos++] = (byte) c; // } // } -// // return ByteString.copyFrom(result, 0, pos); try { return ByteString.copyFrom(ByteArray.fromHexString(input.toString())); @@ -1541,6 +1574,48 @@ public ByteString consumeByteString() throws ParseException { } } + public ByteString consumeByteString(final String fieldName, boolean selfType) + throws ParseException { + char quote = currentToken.length() > 0 ? currentToken.charAt(0) : '\0'; + if ((quote != '\"') && (quote != '\'')) { + throw parseException("Expected string."); + } + + if ((currentToken.length() < 2) + || (currentToken.charAt(currentToken.length() - 1) != quote)) { + throw parseException("String missing ending quote."); + } + + try { + String escaped = currentToken.substring(1, currentToken.length() - 1); + ByteString result; + if (!selfType) { + result = unescapeBytes(escaped); + } else { + result = unescapeBytesSelfType(escaped, fieldName); + } + nextToken(); + return result; + } catch (InvalidEscapeSequence e) { + throw parseException(e.getMessage()); + } + } + + static ByteString unescapeBytesSelfType(String input, final String fliedName) + throws InvalidEscapeSequence { + //Address base58 -> ByteString + if (HttpSelfFormatFieldName.isAddressFormat(fliedName)) { + return ByteString.copyFrom(Wallet.decodeFromBase58Check(input)); + } + + //Normal String -> ByteString + if (HttpSelfFormatFieldName.isNameStringFormat(fliedName)) { + return ByteString.copyFromUtf8(input); + } + + return unescapeBytes(input); + } + /** * Returns a {@link ParseException} with the current line and column numbers in the description, * suitable for throwing. diff --git a/src/main/java/org/tron/core/services/http/ListExchangesServlet.java b/src/main/java/org/tron/core/services/http/ListExchangesServlet.java index 35784b990eb..c1a62420000 100644 --- a/src/main/java/org/tron/core/services/http/ListExchangesServlet.java +++ b/src/main/java/org/tron/core/services/http/ListExchangesServlet.java @@ -19,7 +19,8 @@ public class ListExchangesServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) { try { - response.getWriter().println(JsonFormat.printToString(wallet.getExchangeList())); + boolean visible = Util.getVisible(request); + response.getWriter().println(JsonFormat.printToString(wallet.getExchangeList(), visible)); } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); try { diff --git a/src/main/java/org/tron/core/services/http/ListNodesServlet.java b/src/main/java/org/tron/core/services/http/ListNodesServlet.java index 969fb2e7a4a..3733005b803 100644 --- a/src/main/java/org/tron/core/services/http/ListNodesServlet.java +++ b/src/main/java/org/tron/core/services/http/ListNodesServlet.java @@ -4,6 +4,7 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -20,9 +21,10 @@ public class ListNodesServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { + boolean visible = Util.getVisible(request); NodeList reply = wallet.listNodes(); if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply)); + response.getWriter().println(JsonFormat.printToString(reply, visible)); } else { response.getWriter().println("{}"); } diff --git a/src/main/java/org/tron/core/services/http/ListProposalsServlet.java b/src/main/java/org/tron/core/services/http/ListProposalsServlet.java index 4d8126cac7d..a43871af7aa 100644 --- a/src/main/java/org/tron/core/services/http/ListProposalsServlet.java +++ b/src/main/java/org/tron/core/services/http/ListProposalsServlet.java @@ -4,6 +4,7 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -20,9 +21,10 @@ public class ListProposalsServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { + boolean visible = Util.getVisible(request); ProposalList reply = wallet.getProposalList(); if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply)); + response.getWriter().println(JsonFormat.printToString(reply, visible)); } else { response.getWriter().println("{}"); } diff --git a/src/main/java/org/tron/core/services/http/ListWitnessesServlet.java b/src/main/java/org/tron/core/services/http/ListWitnessesServlet.java index 54b49a9118a..aa5f1086a07 100644 --- a/src/main/java/org/tron/core/services/http/ListWitnessesServlet.java +++ b/src/main/java/org/tron/core/services/http/ListWitnessesServlet.java @@ -4,6 +4,7 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -20,9 +21,10 @@ public class ListWitnessesServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { + boolean visible = Util.getVisible(request); WitnessList reply = wallet.getWitnessList(); if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply)); + response.getWriter().println(JsonFormat.printToString(reply, visible)); } else { response.getWriter().println("{}"); } diff --git a/src/main/java/org/tron/core/services/http/ParticipateAssetIssueServlet.java b/src/main/java/org/tron/core/services/http/ParticipateAssetIssueServlet.java index 58b973b6539..a7acfdf80cd 100644 --- a/src/main/java/org/tron/core/services/http/ParticipateAssetIssueServlet.java +++ b/src/main/java/org/tron/core/services/http/ParticipateAssetIssueServlet.java @@ -1,5 +1,6 @@ package org.tron.core.services.http; +import com.alibaba.fastjson.JSONObject; import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; @@ -30,12 +31,15 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String contract = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(contract); + boolean visible = Util.getVisiblePost(contract); ParticipateAssetIssueContract.Builder build = ParticipateAssetIssueContract.newBuilder(); - JsonFormat.merge(contract, build); + JsonFormat.merge(contract, build, visible); Transaction tx = wallet .createTransactionCapsule(build.build(), ContractType.ParticipateAssetIssueContract) .getInstance(); - response.getWriter().println(Util.printTransaction(tx)); + JSONObject jsonObject = JSONObject.parseObject(contract); + tx = Util.setTransactionPermissionId(jsonObject, tx); + response.getWriter().println(Util.printCreateTransaction(tx, visible)); } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); try { diff --git a/src/main/java/org/tron/core/services/http/ProposalApproveServlet.java b/src/main/java/org/tron/core/services/http/ProposalApproveServlet.java index 9d37208519c..318684ed911 100644 --- a/src/main/java/org/tron/core/services/http/ProposalApproveServlet.java +++ b/src/main/java/org/tron/core/services/http/ProposalApproveServlet.java @@ -1,5 +1,6 @@ package org.tron.core.services.http; +import com.alibaba.fastjson.JSONObject; import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; @@ -30,12 +31,15 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String contract = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(contract); + boolean visible = Util.getVisiblePost(contract); ProposalApproveContract.Builder build = ProposalApproveContract.newBuilder(); - JsonFormat.merge(contract, build); + JsonFormat.merge(contract, build, visible); Transaction tx = wallet .createTransactionCapsule(build.build(), ContractType.ProposalApproveContract) .getInstance(); - response.getWriter().println(Util.printTransaction(tx)); + JSONObject jsonObject = JSONObject.parseObject(contract); + tx = Util.setTransactionPermissionId(jsonObject, tx); + response.getWriter().println(Util.printCreateTransaction(tx, visible)); } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); try { diff --git a/src/main/java/org/tron/core/services/http/ProposalCreateServlet.java b/src/main/java/org/tron/core/services/http/ProposalCreateServlet.java index 3214c8c7670..a8cf16d5252 100644 --- a/src/main/java/org/tron/core/services/http/ProposalCreateServlet.java +++ b/src/main/java/org/tron/core/services/http/ProposalCreateServlet.java @@ -1,5 +1,6 @@ package org.tron.core.services.http; +import com.alibaba.fastjson.JSONObject; import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; @@ -30,12 +31,15 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String contract = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(contract); + boolean visible = Util.getVisiblePost(contract); ProposalCreateContract.Builder build = ProposalCreateContract.newBuilder(); - JsonFormat.merge(contract, build); + JsonFormat.merge(contract, build, visible); Transaction tx = wallet .createTransactionCapsule(build.build(), ContractType.ProposalCreateContract) .getInstance(); - response.getWriter().println(Util.printTransaction(tx)); + JSONObject jsonObject = JSONObject.parseObject(contract); + tx = Util.setTransactionPermissionId(jsonObject, tx); + response.getWriter().println(Util.printCreateTransaction(tx, visible)); } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); try { diff --git a/src/main/java/org/tron/core/services/http/ProposalDeleteServlet.java b/src/main/java/org/tron/core/services/http/ProposalDeleteServlet.java index f94f59ce52a..39636528023 100644 --- a/src/main/java/org/tron/core/services/http/ProposalDeleteServlet.java +++ b/src/main/java/org/tron/core/services/http/ProposalDeleteServlet.java @@ -1,5 +1,6 @@ package org.tron.core.services.http; +import com.alibaba.fastjson.JSONObject; import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; @@ -30,12 +31,15 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String contract = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(contract); + boolean visible = Util.getVisiblePost(contract); ProposalDeleteContract.Builder build = ProposalDeleteContract.newBuilder(); - JsonFormat.merge(contract, build); + JsonFormat.merge(contract, build, visible); Transaction tx = wallet .createTransactionCapsule(build.build(), ContractType.ProposalDeleteContract) .getInstance(); - response.getWriter().println(Util.printTransaction(tx)); + JSONObject jsonObject = JSONObject.parseObject(contract); + tx = Util.setTransactionPermissionId(jsonObject, tx); + response.getWriter().println(Util.printCreateTransaction(tx, visible)); } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); try { diff --git a/src/main/java/org/tron/core/services/http/SetAccountIdServlet.java b/src/main/java/org/tron/core/services/http/SetAccountIdServlet.java new file mode 100644 index 00000000000..56e63969c04 --- /dev/null +++ b/src/main/java/org/tron/core/services/http/SetAccountIdServlet.java @@ -0,0 +1,49 @@ +package org.tron.core.services.http; + +import com.alibaba.fastjson.JSONObject; +import java.io.IOException; +import java.util.stream.Collectors; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.Wallet; +import org.tron.protos.Contract; +import org.tron.protos.Protocol; + + +@Component +@Slf4j(topic = "API") +public class SetAccountIdServlet extends HttpServlet { + @Autowired + private Wallet wallet; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + try { + String contract = request.getReader().lines() + .collect(Collectors.joining(System.lineSeparator())); + Util.checkBodySize(contract); + boolean visible = Util.getVisiblePost(contract); + Contract.SetAccountIdContract.Builder build = Contract.SetAccountIdContract.newBuilder(); + JsonFormat.merge(contract, build, visible); + Protocol.Transaction tx = wallet.createTransactionCapsule(build.build(), + Protocol.Transaction.Contract.ContractType.SetAccountIdContract).getInstance(); + JSONObject jsonObject = JSONObject.parseObject(contract); + tx = Util.setTransactionPermissionId(jsonObject, tx); + response.getWriter().println(Util.printCreateTransaction(tx, visible)); + } catch (Exception e) { + logger.debug("Exception: {}", e.getMessage()); + try { + response.getWriter().println(Util.printErrorMsg(e)); + } catch (IOException ioe) { + logger.debug("IOException: {}", ioe.getMessage()); + } + } + } +} diff --git a/src/main/java/org/tron/core/services/http/TotalTransactionServlet.java b/src/main/java/org/tron/core/services/http/TotalTransactionServlet.java index 77cd57adca4..a4f65636c36 100644 --- a/src/main/java/org/tron/core/services/http/TotalTransactionServlet.java +++ b/src/main/java/org/tron/core/services/http/TotalTransactionServlet.java @@ -4,12 +4,14 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tron.api.GrpcAPI.NumberMessage; import org.tron.core.Wallet; + @Component @Slf4j(topic = "API") public class TotalTransactionServlet extends HttpServlet { @@ -19,9 +21,10 @@ public class TotalTransactionServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { + boolean visible = Util.getVisible(request); NumberMessage reply = wallet.totalTransaction(); if (reply != null) { - response.getWriter().println(JsonFormat.printToString(reply)); + response.getWriter().println(JsonFormat.printToString(reply, visible)); } else { response.getWriter().println("{}"); } diff --git a/src/main/java/org/tron/core/services/http/TransactionSignServlet.java b/src/main/java/org/tron/core/services/http/TransactionSignServlet.java index 68ef640b944..362e6e7c180 100644 --- a/src/main/java/org/tron/core/services/http/TransactionSignServlet.java +++ b/src/main/java/org/tron/core/services/http/TransactionSignServlet.java @@ -1,11 +1,13 @@ package org.tron.core.services.http; import com.alibaba.fastjson.JSONObject; + import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -32,15 +34,17 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(contract); JSONObject input = JSONObject.parseObject(contract); + boolean visible = Util.getVisibleOnlyForSign(input); String strTransaction = input.getJSONObject("transaction").toJSONString(); - Transaction transaction = Util.packTransaction(strTransaction); - JSONObject jsonTransaction = JSONObject.parseObject(JsonFormat.printToString(transaction)); + Transaction transaction = Util.packTransaction(strTransaction, visible); + JSONObject jsonTransaction = JSONObject.parseObject(JsonFormat.printToString(transaction, + visible)); input.put("transaction", jsonTransaction); TransactionSign.Builder build = TransactionSign.newBuilder(); - JsonFormat.merge(input.toJSONString(), build); + JsonFormat.merge(input.toJSONString(), build, visible); TransactionCapsule reply = wallet.getTransactionSign(build.build()); if (reply != null) { - response.getWriter().println(Util.printTransaction(reply.getInstance())); + response.getWriter().println(Util.printCreateTransaction(reply.getInstance(), visible)); } else { response.getWriter().println("{}"); } diff --git a/src/main/java/org/tron/core/services/http/TransferAssetServlet.java b/src/main/java/org/tron/core/services/http/TransferAssetServlet.java index a645e299472..f0033256a23 100644 --- a/src/main/java/org/tron/core/services/http/TransferAssetServlet.java +++ b/src/main/java/org/tron/core/services/http/TransferAssetServlet.java @@ -1,10 +1,13 @@ package org.tron.core.services.http; +import com.alibaba.fastjson.JSONObject; + import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -30,12 +33,15 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String contract = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(contract); + boolean visible = Util.getVisiblePost(contract); TransferAssetContract.Builder build = TransferAssetContract.newBuilder(); - JsonFormat.merge(contract, build); + JsonFormat.merge(contract, build, visible); Transaction tx = wallet .createTransactionCapsule(build.build(), ContractType.TransferAssetContract) .getInstance(); - response.getWriter().println(Util.printTransaction(tx)); + JSONObject jsonObject = JSONObject.parseObject(contract); + tx = Util.setTransactionPermissionId(jsonObject, tx); + response.getWriter().println(Util.printCreateTransaction(tx, visible)); } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); try { diff --git a/src/main/java/org/tron/core/services/http/TransferServlet.java b/src/main/java/org/tron/core/services/http/TransferServlet.java index 3fa5b18a933..b54d017c97c 100644 --- a/src/main/java/org/tron/core/services/http/TransferServlet.java +++ b/src/main/java/org/tron/core/services/http/TransferServlet.java @@ -1,10 +1,13 @@ package org.tron.core.services.http; +import com.alibaba.fastjson.JSONObject; + import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -30,11 +33,14 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String contract = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(contract); + boolean visible = Util.getVisiblePost(contract); TransferContract.Builder build = TransferContract.newBuilder(); - JsonFormat.merge(contract, build); + JsonFormat.merge(contract, build, visible); Transaction tx = wallet.createTransactionCapsule(build.build(), ContractType.TransferContract) .getInstance(); - response.getWriter().println(Util.printTransaction(tx)); + JSONObject jsonObject = JSONObject.parseObject(contract); + tx = Util.setTransactionPermissionId(jsonObject, tx); + response.getWriter().println(Util.printCreateTransaction(tx, visible)); } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); try { diff --git a/src/main/java/org/tron/core/services/http/TriggerConstantContractServlet.java b/src/main/java/org/tron/core/services/http/TriggerConstantContractServlet.java new file mode 100644 index 00000000000..807f8e67190 --- /dev/null +++ b/src/main/java/org/tron/core/services/http/TriggerConstantContractServlet.java @@ -0,0 +1,105 @@ +package org.tron.core.services.http; + +import com.alibaba.fastjson.JSONObject; +import com.google.protobuf.ByteString; + +import io.netty.util.internal.StringUtil; +import java.io.IOException; +import java.security.InvalidParameterException; +import java.util.stream.Collectors; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.api.GrpcAPI.Return; +import org.tron.api.GrpcAPI.Return.response_code; +import org.tron.api.GrpcAPI.TransactionExtention; +import org.tron.common.utils.ByteArray; +import org.tron.core.Wallet; +import org.tron.core.capsule.TransactionCapsule; +import org.tron.core.exception.ContractValidateException; +import org.tron.protos.Contract.TriggerSmartContract; +import org.tron.protos.Protocol.Transaction; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; + + +@Component +@Slf4j(topic = "API") +public class TriggerConstantContractServlet extends HttpServlet { + private final String functionSelector = "function_selector"; + + @Autowired + private Wallet wallet; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + } + + protected void validateParameter(String contract) { + JSONObject jsonObject = JSONObject.parseObject(contract); + if (!jsonObject.containsKey("owner_address") + || StringUtil.isNullOrEmpty(jsonObject.getString("owner_address"))) { + throw new InvalidParameterException("owner_address isn't set."); + } + if (!jsonObject.containsKey("contract_address") + || StringUtil.isNullOrEmpty(jsonObject.getString("contract_address"))) { + throw new InvalidParameterException("contract_address isn't set."); + } + if (!jsonObject.containsKey(functionSelector) + || StringUtil.isNullOrEmpty(jsonObject.getString(functionSelector))) { + throw new InvalidParameterException("function_selector isn't set."); + } + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) + throws IOException { + TriggerSmartContract.Builder build = TriggerSmartContract.newBuilder(); + TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); + Return.Builder retBuilder = Return.newBuilder(); + boolean visible = false; + try { + String contract = request.getReader().lines() + .collect(Collectors.joining(System.lineSeparator())); + Util.checkBodySize(contract); + visible = Util.getVisiblePost(contract); + validateParameter(contract); + JsonFormat.merge(contract, build, visible); + JSONObject jsonObject = JSONObject.parseObject(contract); + String selector = jsonObject.getString(functionSelector); + String parameter = jsonObject.getString("parameter"); + String data = Util.parseMethod(selector, parameter); + build.setData(ByteString.copyFrom(ByteArray.fromHexString(data))); + long feeLimit = Util.getJsonLongValue(jsonObject, "fee_limit"); + + TransactionCapsule trxCap = wallet + .createTransactionCapsule(build.build(), ContractType.TriggerSmartContract); + + Transaction.Builder txBuilder = trxCap.getInstance().toBuilder(); + Transaction.raw.Builder rawBuilder = trxCap.getInstance().getRawData().toBuilder(); + rawBuilder.setFeeLimit(feeLimit); + txBuilder.setRawData(rawBuilder); + + Transaction trx = wallet + .triggerConstantContract(build.build(), new TransactionCapsule(txBuilder.build()), + trxExtBuilder, + retBuilder); + trx = Util.setTransactionPermissionId(jsonObject, trx); + trxExtBuilder.setTransaction(trx); + retBuilder.setResult(true).setCode(response_code.SUCCESS); + } catch (ContractValidateException e) { + retBuilder.setResult(false).setCode(response_code.CONTRACT_VALIDATE_ERROR) + .setMessage(ByteString.copyFromUtf8(e.getMessage())); + } catch (Exception e) { + String errString = null; + if (e.getMessage() != null) { + errString = e.getMessage().replaceAll("[\"]", "\'"); + } + retBuilder.setResult(false).setCode(response_code.OTHER_ERROR) + .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + errString)); + } + trxExtBuilder.setResult(retBuilder); + response.getWriter().println(Util.printTransactionExtention(trxExtBuilder.build(), visible)); + } +} \ No newline at end of file diff --git a/src/main/java/org/tron/core/services/http/TriggerSmartContractServlet.java b/src/main/java/org/tron/core/services/http/TriggerSmartContractServlet.java index be1d514b5d4..e97f4305931 100644 --- a/src/main/java/org/tron/core/services/http/TriggerSmartContractServlet.java +++ b/src/main/java/org/tron/core/services/http/TriggerSmartContractServlet.java @@ -2,11 +2,15 @@ import com.alibaba.fastjson.JSONObject; import com.google.protobuf.ByteString; + +import io.netty.util.internal.StringUtil; import java.io.IOException; +import java.security.InvalidParameterException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.spongycastle.util.encoders.Hex; @@ -15,7 +19,6 @@ import org.tron.api.GrpcAPI.Return; import org.tron.api.GrpcAPI.Return.response_code; import org.tron.api.GrpcAPI.TransactionExtention; -import org.tron.common.crypto.Hash; import org.tron.common.utils.ByteArray; import org.tron.core.Wallet; import org.tron.core.capsule.TransactionCapsule; @@ -29,21 +32,28 @@ @Slf4j(topic = "API") public class TriggerSmartContractServlet extends HttpServlet { + private final String functionSelector = "function_selector"; + @Autowired private Wallet wallet; protected void doGet(HttpServletRequest request, HttpServletResponse response) { } - public static String parseMethod(String methodSign, String params) { - byte[] selector = new byte[4]; - System.arraycopy(Hash.sha3(methodSign.getBytes()), 0, selector, 0, 4); - System.out.println(methodSign + ":" + Hex.toHexString(selector)); - if (StringUtils.isEmpty(params)) { - return Hex.toHexString(selector); + protected void validateParameter(String contract) { + JSONObject jsonObject = JSONObject.parseObject(contract); + if (!jsonObject.containsKey("owner_address") + || StringUtil.isNullOrEmpty(jsonObject.getString("owner_address"))) { + throw new InvalidParameterException("owner_address isn't set."); + } + if (!jsonObject.containsKey("contract_address") + || StringUtil.isNullOrEmpty(jsonObject.getString("contract_address"))) { + throw new InvalidParameterException("contract_address isn't set."); + } + if (!jsonObject.containsKey(functionSelector) + || StringUtil.isNullOrEmpty(jsonObject.getString(functionSelector))) { + throw new InvalidParameterException("function_selector isn't set."); } - String result = Hex.toHexString(selector) + params; - return result; } protected void doPost(HttpServletRequest request, HttpServletResponse response) @@ -51,20 +61,24 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) TriggerSmartContract.Builder build = TriggerSmartContract.newBuilder(); TransactionExtention.Builder trxExtBuilder = TransactionExtention.newBuilder(); Return.Builder retBuilder = Return.newBuilder(); + boolean visible = false; try { String contract = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(contract); - JsonFormat.merge(contract, build); + visible = Util.getVisiblePost(contract); + validateParameter(contract); + JsonFormat.merge(contract, build, visible); JSONObject jsonObject = JSONObject.parseObject(contract); - String selector = jsonObject.getString("function_selector"); + String selector = jsonObject.getString(functionSelector); String parameter = jsonObject.getString("parameter"); - String data = parseMethod(selector, parameter); + String data = Util.parseMethod(selector, parameter); build.setData(ByteString.copyFrom(ByteArray.fromHexString(data))); - - long feeLimit = jsonObject.getLongValue("fee_limit"); - + build.setCallTokenValue(Util.getJsonLongValue(jsonObject, "call_token_value")); + build.setTokenId(Util.getJsonLongValue(jsonObject, "token_id")); + build.setCallValue(Util.getJsonLongValue(jsonObject, "call_value")); + long feeLimit = Util.getJsonLongValue(jsonObject, "fee_limit"); TransactionCapsule trxCap = wallet .createTransactionCapsule(build.build(), ContractType.TriggerSmartContract); @@ -76,16 +90,21 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) Transaction trx = wallet .triggerContract(build.build(), new TransactionCapsule(txBuilder.build()), trxExtBuilder, retBuilder); + trx = Util.setTransactionPermissionId(jsonObject, trx); trxExtBuilder.setTransaction(trx); retBuilder.setResult(true).setCode(response_code.SUCCESS); } catch (ContractValidateException e) { retBuilder.setResult(false).setCode(response_code.CONTRACT_VALIDATE_ERROR) .setMessage(ByteString.copyFromUtf8(e.getMessage())); } catch (Exception e) { + String errString = null; + if (e.getMessage() != null) { + errString = e.getMessage().replaceAll("[\"]", "\'"); + } retBuilder.setResult(false).setCode(response_code.OTHER_ERROR) - .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + e.getMessage())); + .setMessage(ByteString.copyFromUtf8(e.getClass() + " : " + errString)); } trxExtBuilder.setResult(retBuilder); - response.getWriter().println(Util.printTransactionExtention(trxExtBuilder.build())); + response.getWriter().println(Util.printTransactionExtention(trxExtBuilder.build(), visible)); } } \ No newline at end of file diff --git a/src/main/java/org/tron/core/services/http/UnFreezeAssetServlet.java b/src/main/java/org/tron/core/services/http/UnFreezeAssetServlet.java index 1fbfc9b2299..f26ece9949a 100644 --- a/src/main/java/org/tron/core/services/http/UnFreezeAssetServlet.java +++ b/src/main/java/org/tron/core/services/http/UnFreezeAssetServlet.java @@ -1,10 +1,13 @@ package org.tron.core.services.http; +import com.alibaba.fastjson.JSONObject; + import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -30,12 +33,15 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String contract = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(contract); + boolean visible = Util.getVisiblePost(contract); UnfreezeAssetContract.Builder build = UnfreezeAssetContract.newBuilder(); - JsonFormat.merge(contract, build); + JsonFormat.merge(contract, build, visible); Transaction tx = wallet .createTransactionCapsule(build.build(), ContractType.UnfreezeAssetContract) .getInstance(); - response.getWriter().println(Util.printTransaction(tx)); + JSONObject jsonObject = JSONObject.parseObject(contract); + tx = Util.setTransactionPermissionId(jsonObject, tx); + response.getWriter().println(Util.printCreateTransaction(tx, visible)); } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); try { diff --git a/src/main/java/org/tron/core/services/http/UnFreezeBalanceServlet.java b/src/main/java/org/tron/core/services/http/UnFreezeBalanceServlet.java index f62840cd25e..fd7187bd738 100644 --- a/src/main/java/org/tron/core/services/http/UnFreezeBalanceServlet.java +++ b/src/main/java/org/tron/core/services/http/UnFreezeBalanceServlet.java @@ -1,5 +1,6 @@ package org.tron.core.services.http; +import com.alibaba.fastjson.JSONObject; import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; @@ -30,12 +31,15 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String contract = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(contract); + boolean visible = Util.getVisiblePost(contract); UnfreezeBalanceContract.Builder build = UnfreezeBalanceContract.newBuilder(); - JsonFormat.merge(contract, build); + JsonFormat.merge(contract, build, visible); Transaction tx = wallet .createTransactionCapsule(build.build(), ContractType.UnfreezeBalanceContract) .getInstance(); - response.getWriter().println(Util.printTransaction(tx)); + JSONObject jsonObject = JSONObject.parseObject(contract); + tx = Util.setTransactionPermissionId(jsonObject, tx); + response.getWriter().println(Util.printCreateTransaction(tx, visible)); } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); try { diff --git a/src/main/java/org/tron/core/services/http/UpdateAccountServlet.java b/src/main/java/org/tron/core/services/http/UpdateAccountServlet.java index 08754bcd877..070a97fb10e 100644 --- a/src/main/java/org/tron/core/services/http/UpdateAccountServlet.java +++ b/src/main/java/org/tron/core/services/http/UpdateAccountServlet.java @@ -1,10 +1,13 @@ package org.tron.core.services.http; +import com.alibaba.fastjson.JSONObject; + import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -30,12 +33,15 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String contract = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(contract); + boolean visible = Util.getVisiblePost(contract); AccountUpdateContract.Builder build = AccountUpdateContract.newBuilder(); - JsonFormat.merge(contract, build); + JsonFormat.merge(contract, build, visible); Transaction tx = wallet .createTransactionCapsule(build.build(), ContractType.AccountUpdateContract) .getInstance(); - response.getWriter().println(Util.printTransaction(tx)); + JSONObject jsonObject = JSONObject.parseObject(contract); + tx = Util.setTransactionPermissionId(jsonObject, tx); + response.getWriter().println(Util.printCreateTransaction(tx, visible)); } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); try { diff --git a/src/main/java/org/tron/core/services/http/UpdateAssetServlet.java b/src/main/java/org/tron/core/services/http/UpdateAssetServlet.java index c316acba3aa..13f34a4dcd2 100644 --- a/src/main/java/org/tron/core/services/http/UpdateAssetServlet.java +++ b/src/main/java/org/tron/core/services/http/UpdateAssetServlet.java @@ -1,10 +1,13 @@ package org.tron.core.services.http; +import com.alibaba.fastjson.JSONObject; + import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -30,11 +33,15 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String contract = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(contract); + boolean visible = Util.getVisiblePost(contract); UpdateAssetContract.Builder build = UpdateAssetContract.newBuilder(); - JsonFormat.merge(contract, build); + JsonFormat.merge(contract, build, visible); Transaction tx = wallet .createTransactionCapsule(build.build(), ContractType.UpdateAssetContract).getInstance(); - response.getWriter().println(Util.printTransaction(tx)); + JSONObject jsonObject = JSONObject.parseObject(contract); + tx = Util.setTransactionPermissionId(jsonObject, tx); + + response.getWriter().println(Util.printCreateTransaction(tx, visible)); } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); try { diff --git a/src/main/java/org/tron/core/services/http/UpdateEnergyLimitServlet.java b/src/main/java/org/tron/core/services/http/UpdateEnergyLimitServlet.java index d34d15e04d6..0f92fa2001d 100644 --- a/src/main/java/org/tron/core/services/http/UpdateEnergyLimitServlet.java +++ b/src/main/java/org/tron/core/services/http/UpdateEnergyLimitServlet.java @@ -1,10 +1,13 @@ package org.tron.core.services.http; +import com.alibaba.fastjson.JSONObject; + import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -30,12 +33,16 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String contract = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(contract); + boolean visible = Util.getVisiblePost(contract); UpdateEnergyLimitContract.Builder build = UpdateEnergyLimitContract.newBuilder(); - JsonFormat.merge(contract, build); + JsonFormat.merge(contract, build, visible); Transaction tx = wallet .createTransactionCapsule(build.build(), ContractType.UpdateEnergyLimitContract) .getInstance(); - response.getWriter().println(Util.printTransaction(tx)); + JSONObject jsonObject = JSONObject.parseObject(contract); + tx = Util.setTransactionPermissionId(jsonObject, tx); + + response.getWriter().println(Util.printCreateTransaction(tx, visible)); } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); try { diff --git a/src/main/java/org/tron/core/services/http/UpdateSettingServlet.java b/src/main/java/org/tron/core/services/http/UpdateSettingServlet.java index bf1a613dc2a..ea4f265d578 100644 --- a/src/main/java/org/tron/core/services/http/UpdateSettingServlet.java +++ b/src/main/java/org/tron/core/services/http/UpdateSettingServlet.java @@ -1,10 +1,13 @@ package org.tron.core.services.http; +import com.alibaba.fastjson.JSONObject; + import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -30,12 +33,16 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String contract = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(contract); + boolean visible = Util.getVisiblePost(contract); UpdateSettingContract.Builder build = UpdateSettingContract.newBuilder(); - JsonFormat.merge(contract, build); + JsonFormat.merge(contract, build, visible); Transaction tx = wallet .createTransactionCapsule(build.build(), ContractType.UpdateSettingContract) .getInstance(); - response.getWriter().println(Util.printTransaction(tx)); + JSONObject jsonObject = JSONObject.parseObject(contract); + tx = Util.setTransactionPermissionId(jsonObject, tx); + + response.getWriter().println(Util.printCreateTransaction(tx, visible)); } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); try { diff --git a/src/main/java/org/tron/core/services/http/UpdateWitnessServlet.java b/src/main/java/org/tron/core/services/http/UpdateWitnessServlet.java index 6fda2b08b6e..82aa259cd22 100644 --- a/src/main/java/org/tron/core/services/http/UpdateWitnessServlet.java +++ b/src/main/java/org/tron/core/services/http/UpdateWitnessServlet.java @@ -1,5 +1,6 @@ package org.tron.core.services.http; +import com.alibaba.fastjson.JSONObject; import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; @@ -30,12 +31,15 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String contract = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(contract); + boolean visible = Util.getVisiblePost(contract); WitnessUpdateContract.Builder build = WitnessUpdateContract.newBuilder(); - JsonFormat.merge(contract, build); + JsonFormat.merge(contract, build, visible); Transaction tx = wallet .createTransactionCapsule(build.build(), ContractType.WitnessUpdateContract) .getInstance(); - response.getWriter().println(Util.printTransaction(tx)); + JSONObject jsonObject = JSONObject.parseObject(contract); + tx = Util.setTransactionPermissionId(jsonObject, tx); + response.getWriter().println(Util.printCreateTransaction(tx, visible)); } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); try { diff --git a/src/main/java/org/tron/core/services/http/Util.java b/src/main/java/org/tron/core/services/http/Util.java index e2832793d54..de9763d7dfb 100644 --- a/src/main/java/org/tron/core/services/http/Util.java +++ b/src/main/java/org/tron/core/services/http/Util.java @@ -1,11 +1,21 @@ package org.tron.core.services.http; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.google.protobuf.Any; +import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; + +import java.math.BigDecimal; +import java.security.InvalidParameterException; import java.util.List; +import javax.servlet.http.HttpServletRequest; + import lombok.extern.slf4j.Slf4j; +import org.eclipse.jetty.util.StringUtil; +import org.pf4j.util.StringUtils; +import org.spongycastle.util.encoders.Hex; import org.tron.api.GrpcAPI.BlockList; import org.tron.api.GrpcAPI.EasyTransferResponse; import org.tron.api.GrpcAPI.TransactionApprovedList; @@ -15,10 +25,12 @@ import org.tron.common.crypto.Hash; import org.tron.common.utils.ByteArray; import org.tron.common.utils.Sha256Hash; +import org.tron.core.Wallet; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.TransactionCapsule; import org.tron.core.config.args.Args; import org.tron.core.services.http.JsonFormat.ParseException; +import org.tron.protos.Contract; import org.tron.protos.Contract.AccountCreateContract; import org.tron.protos.Contract.AccountPermissionUpdateContract; import org.tron.protos.Contract.AccountUpdateContract; @@ -47,105 +59,122 @@ import org.tron.protos.Contract.WitnessCreateContract; import org.tron.protos.Contract.WitnessUpdateContract; import org.tron.protos.Protocol.Block; -import org.tron.protos.Protocol.SmartContract; import org.tron.protos.Protocol.Transaction; - @Slf4j(topic = "API") public class Util { + public static final String PERMISSION_ID = "Permission_id"; + public static final String VISIBLE = "visible"; + public static final String TRANSACTION = "transaction"; + public static final String VALUE = "value"; + public static String printErrorMsg(Exception e) { JSONObject jsonObject = new JSONObject(); jsonObject.put("Error", e.getClass() + " : " + e.getMessage()); return jsonObject.toJSONString(); } - public static String printBlockList(BlockList list) { + public static String printBlockList(BlockList list, boolean selfType) { List blocks = list.getBlockList(); - JSONObject jsonObject = JSONObject.parseObject(JsonFormat.printToString(list)); + JSONObject jsonObject = JSONObject.parseObject(JsonFormat.printToString(list, selfType)); JSONArray jsonArray = new JSONArray(); blocks.stream().forEach(block -> { - jsonArray.add(printBlockToJSON(block)); + jsonArray.add(printBlockToJSON(block, selfType)); }); jsonObject.put("block", jsonArray); return jsonObject.toJSONString(); } - public static String printBlock(Block block) { - return printBlockToJSON(block).toJSONString(); + public static String printBlock(Block block, boolean selfType) { + return printBlockToJSON(block, selfType).toJSONString(); } - public static JSONObject printBlockToJSON(Block block) { + public static JSONObject printBlockToJSON(Block block, boolean selfType) { BlockCapsule blockCapsule = new BlockCapsule(block); String blockID = ByteArray.toHexString(blockCapsule.getBlockId().getBytes()); - JSONObject jsonObject = JSONObject.parseObject(JsonFormat.printToString(block)); + JSONObject jsonObject = JSONObject.parseObject(JsonFormat.printToString(block, selfType)); jsonObject.put("blockID", blockID); if (!blockCapsule.getTransactions().isEmpty()) { - jsonObject.put("transactions", printTransactionListToJSON(blockCapsule.getTransactions())); + jsonObject.put("transactions", printTransactionListToJSON(blockCapsule.getTransactions(), + selfType)); } return jsonObject; } - public static String printTransactionList(TransactionList list) { + public static String printTransactionList(TransactionList list, boolean selfType) { List transactions = list.getTransactionList(); - JSONObject jsonObject = JSONObject.parseObject(JsonFormat.printToString(list)); + JSONObject jsonObject = JSONObject.parseObject(JsonFormat.printToString(list, selfType)); JSONArray jsonArray = new JSONArray(); transactions.stream().forEach(transaction -> { - jsonArray.add(printTransactionToJSON(transaction)); + jsonArray.add(printTransactionToJSON(transaction, selfType)); }); - jsonObject.put("transaction", jsonArray); + jsonObject.put(TRANSACTION, jsonArray); return jsonObject.toJSONString(); } - public static JSONArray printTransactionListToJSON(List list) { + public static JSONArray printTransactionListToJSON(List list, + boolean selfType) { JSONArray transactions = new JSONArray(); list.stream().forEach(transactionCapsule -> { - transactions.add(printTransactionToJSON(transactionCapsule.getInstance())); + transactions.add(printTransactionToJSON(transactionCapsule.getInstance(), selfType)); }); return transactions; } - public static String printEasyTransferResponse(EasyTransferResponse response) { - JSONObject jsonResponse = JSONObject.parseObject(JsonFormat.printToString(response)); - jsonResponse.put("transaction", printTransactionToJSON(response.getTransaction())); + public static String printEasyTransferResponse(EasyTransferResponse response, boolean selfType) { + JSONObject jsonResponse = JSONObject.parseObject(JsonFormat.printToString(response, selfType)); + jsonResponse.put(TRANSACTION, printTransactionToJSON(response.getTransaction(), selfType)); return jsonResponse.toJSONString(); } - public static String printTransaction(Transaction transaction) { - return printTransactionToJSON(transaction).toJSONString(); + public static String printTransaction(Transaction transaction, boolean selfType) { + return printTransactionToJSON(transaction, selfType).toJSONString(); } - public static String printTransactionExtention(TransactionExtention transactionExtention) { - String string = JsonFormat.printToString(transactionExtention); + public static String printCreateTransaction(Transaction transaction, boolean selfType) { + JSONObject jsonObject = printTransactionToJSON(transaction, selfType); + jsonObject.put(VISIBLE, selfType); + return jsonObject.toJSONString(); + } + + public static String printTransactionExtention(TransactionExtention transactionExtention, + boolean selfType) { + String string = JsonFormat.printToString(transactionExtention, selfType); JSONObject jsonObject = JSONObject.parseObject(string); if (transactionExtention.getResult().getResult()) { - jsonObject.put("transaction", printTransactionToJSON(transactionExtention.getTransaction())); + JSONObject transactionOjbect = printTransactionToJSON( + transactionExtention.getTransaction(), selfType); + transactionOjbect.put(VISIBLE, selfType); + jsonObject.put(TRANSACTION, transactionOjbect); } return jsonObject.toJSONString(); } - public static String printTransactionSignWeight(TransactionSignWeight transactionSignWeight) { - String string = JsonFormat.printToString(transactionSignWeight); + public static String printTransactionSignWeight(TransactionSignWeight transactionSignWeight, + boolean selfType) { + String string = JsonFormat.printToString(transactionSignWeight, selfType); JSONObject jsonObject = JSONObject.parseObject(string); - JSONObject jsonObjectExt = jsonObject.getJSONObject("transaction"); + JSONObject jsonObjectExt = jsonObject.getJSONObject(TRANSACTION); jsonObjectExt - .put("transaction", - printTransactionToJSON(transactionSignWeight.getTransaction().getTransaction())); - jsonObject.put("transaction", jsonObjectExt); + .put(TRANSACTION, + printTransactionToJSON(transactionSignWeight.getTransaction().getTransaction(), + selfType)); + jsonObject.put(TRANSACTION, jsonObjectExt); return jsonObject.toJSONString(); } public static String printTransactionApprovedList( - TransactionApprovedList transactionApprovedList) { - String string = JsonFormat.printToString(transactionApprovedList); + TransactionApprovedList transactionApprovedList, boolean selfType) { + String string = JsonFormat.printToString(transactionApprovedList, selfType); JSONObject jsonObject = JSONObject.parseObject(string); - JSONObject jsonObjectExt = jsonObject.getJSONObject("transaction"); - jsonObjectExt - .put("transaction", - printTransactionToJSON(transactionApprovedList.getTransaction().getTransaction())); - jsonObject.put("transaction", jsonObjectExt); + JSONObject jsonObjectExt = jsonObject.getJSONObject(TRANSACTION); + jsonObjectExt.put(TRANSACTION, + printTransactionToJSON(transactionApprovedList.getTransaction().getTransaction(), + selfType)); + jsonObject.put(TRANSACTION, jsonObjectExt); return jsonObject.toJSONString(); } @@ -161,8 +190,9 @@ public static byte[] generateContractAddress(Transaction trx, byte[] ownerAddres return Hash.sha3omit12(combined); } - public static JSONObject printTransactionToJSON(Transaction transaction) { - JSONObject jsonTransaction = JSONObject.parseObject(JsonFormat.printToString(transaction)); + public static JSONObject printTransactionToJSON(Transaction transaction, boolean selfType) { + JSONObject jsonTransaction = JSONObject.parseObject(JsonFormat.printToString(transaction, + selfType)); JSONArray contracts = new JSONArray(); transaction.getRawData().getContractList().stream().forEach(contract -> { try { @@ -172,156 +202,190 @@ public static JSONObject printTransactionToJSON(Transaction transaction) { case AccountCreateContract: AccountCreateContract accountCreateContract = contractParameter .unpack(AccountCreateContract.class); - contractJson = JSONObject.parseObject(JsonFormat.printToString(accountCreateContract)); + contractJson = JSONObject.parseObject(JsonFormat.printToString(accountCreateContract, + selfType)); break; case TransferContract: TransferContract transferContract = contractParameter.unpack(TransferContract.class); - contractJson = JSONObject.parseObject(JsonFormat.printToString(transferContract)); + contractJson = JSONObject.parseObject(JsonFormat.printToString(transferContract, + selfType)); break; case TransferAssetContract: TransferAssetContract transferAssetContract = contractParameter .unpack(TransferAssetContract.class); - contractJson = JSONObject.parseObject(JsonFormat.printToString(transferAssetContract)); + contractJson = JSONObject.parseObject(JsonFormat.printToString(transferAssetContract, + selfType)); break; case VoteAssetContract: VoteAssetContract voteAssetContract = contractParameter.unpack(VoteAssetContract.class); - contractJson = JSONObject.parseObject(JsonFormat.printToString(voteAssetContract)); + contractJson = JSONObject.parseObject(JsonFormat.printToString(voteAssetContract, + selfType)); break; case VoteWitnessContract: VoteWitnessContract voteWitnessContract = contractParameter .unpack(VoteWitnessContract.class); - contractJson = JSONObject.parseObject(JsonFormat.printToString(voteWitnessContract)); + contractJson = JSONObject.parseObject(JsonFormat.printToString(voteWitnessContract, + selfType)); break; case WitnessCreateContract: WitnessCreateContract witnessCreateContract = contractParameter .unpack(WitnessCreateContract.class); - contractJson = JSONObject.parseObject(JsonFormat.printToString(witnessCreateContract)); + contractJson = JSONObject.parseObject(JsonFormat.printToString(witnessCreateContract, + selfType)); break; case AssetIssueContract: AssetIssueContract assetIssueContract = contractParameter .unpack(AssetIssueContract.class); - contractJson = JSONObject.parseObject(JsonFormat.printToString(assetIssueContract)); + contractJson = JSONObject.parseObject(JsonFormat.printToString(assetIssueContract, + selfType)); break; case WitnessUpdateContract: WitnessUpdateContract witnessUpdateContract = contractParameter .unpack(WitnessUpdateContract.class); - contractJson = JSONObject.parseObject(JsonFormat.printToString(witnessUpdateContract)); + contractJson = JSONObject.parseObject(JsonFormat.printToString(witnessUpdateContract, + selfType)); break; case ParticipateAssetIssueContract: ParticipateAssetIssueContract participateAssetIssueContract = contractParameter .unpack(ParticipateAssetIssueContract.class); contractJson = JSONObject - .parseObject(JsonFormat.printToString(participateAssetIssueContract)); + .parseObject(JsonFormat.printToString(participateAssetIssueContract, selfType)); break; case AccountUpdateContract: AccountUpdateContract accountUpdateContract = contractParameter .unpack(AccountUpdateContract.class); - contractJson = JSONObject.parseObject(JsonFormat.printToString(accountUpdateContract)); + contractJson = JSONObject.parseObject(JsonFormat.printToString(accountUpdateContract, + selfType)); break; case FreezeBalanceContract: FreezeBalanceContract freezeBalanceContract = contractParameter .unpack(FreezeBalanceContract.class); - contractJson = JSONObject.parseObject(JsonFormat.printToString(freezeBalanceContract)); + contractJson = JSONObject.parseObject(JsonFormat.printToString(freezeBalanceContract, + selfType)); break; case UnfreezeBalanceContract: UnfreezeBalanceContract unfreezeBalanceContract = contractParameter .unpack(UnfreezeBalanceContract.class); contractJson = JSONObject - .parseObject(JsonFormat.printToString(unfreezeBalanceContract)); - break; - case UnfreezeAssetContract: - UnfreezeAssetContract unfreezeAssetContract = contractParameter - .unpack(UnfreezeAssetContract.class); - contractJson = JSONObject.parseObject(JsonFormat.printToString(unfreezeAssetContract)); + .parseObject(JsonFormat.printToString(unfreezeBalanceContract, selfType)); break; case WithdrawBalanceContract: WithdrawBalanceContract withdrawBalanceContract = contractParameter .unpack(WithdrawBalanceContract.class); contractJson = JSONObject - .parseObject(JsonFormat.printToString(withdrawBalanceContract)); + .parseObject(JsonFormat.printToString(withdrawBalanceContract, selfType)); + break; + case UnfreezeAssetContract: + UnfreezeAssetContract unfreezeAssetContract = contractParameter + .unpack(UnfreezeAssetContract.class); + contractJson = JSONObject.parseObject(JsonFormat.printToString(unfreezeAssetContract, + selfType)); break; case UpdateAssetContract: UpdateAssetContract updateAssetContract = contractParameter .unpack(UpdateAssetContract.class); - contractJson = JSONObject.parseObject(JsonFormat.printToString(updateAssetContract)); - break; - case CreateSmartContract: - CreateSmartContract deployContract = contractParameter - .unpack(CreateSmartContract.class); - contractJson = JSONObject.parseObject(JsonFormat.printToString(deployContract)); - byte[] ownerAddress = deployContract.getOwnerAddress().toByteArray(); - byte[] contractAddress = generateContractAddress(transaction, ownerAddress); - jsonTransaction.put("contract_address", ByteArray.toHexString(contractAddress)); - break; - case TriggerSmartContract: - TriggerSmartContract triggerSmartContract = contractParameter - .unpack(TriggerSmartContract.class); - contractJson = JSONObject.parseObject(JsonFormat.printToString(triggerSmartContract)); + contractJson = JSONObject.parseObject(JsonFormat.printToString(updateAssetContract, + selfType)); break; case ProposalCreateContract: ProposalCreateContract proposalCreateContract = contractParameter .unpack(ProposalCreateContract.class); - contractJson = JSONObject.parseObject(JsonFormat.printToString(proposalCreateContract)); + contractJson = JSONObject.parseObject(JsonFormat.printToString(proposalCreateContract, + selfType)); break; case ProposalApproveContract: ProposalApproveContract proposalApproveContract = contractParameter .unpack(ProposalApproveContract.class); contractJson = JSONObject - .parseObject(JsonFormat.printToString(proposalApproveContract)); + .parseObject(JsonFormat.printToString(proposalApproveContract, selfType)); break; case ProposalDeleteContract: ProposalDeleteContract proposalDeleteContract = contractParameter .unpack(ProposalDeleteContract.class); - contractJson = JSONObject.parseObject(JsonFormat.printToString(proposalDeleteContract)); + contractJson = JSONObject.parseObject(JsonFormat.printToString(proposalDeleteContract, + selfType)); + break; + case SetAccountIdContract: + Contract.SetAccountIdContract setAccountIdContract = + contractParameter.unpack(Contract.SetAccountIdContract.class); + contractJson = JSONObject.parseObject(JsonFormat.printToString(setAccountIdContract, + selfType)); + break; + case CreateSmartContract: + CreateSmartContract deployContract = contractParameter + .unpack(CreateSmartContract.class); + contractJson = JSONObject.parseObject(JsonFormat.printToString(deployContract, + selfType)); + byte[] ownerAddress = deployContract.getOwnerAddress().toByteArray(); + byte[] contractAddress = generateContractAddress(transaction, ownerAddress); + jsonTransaction.put("contract_address", ByteArray.toHexString(contractAddress)); + break; + case TriggerSmartContract: + TriggerSmartContract triggerSmartContract = contractParameter + .unpack(TriggerSmartContract.class); + contractJson = JSONObject.parseObject(JsonFormat.printToString(triggerSmartContract, + selfType)); + break; + case UpdateSettingContract: + UpdateSettingContract updateSettingContract = contractParameter + .unpack(UpdateSettingContract.class); + contractJson = JSONObject.parseObject(JsonFormat.printToString(updateSettingContract, + selfType)); break; case ExchangeCreateContract: ExchangeCreateContract exchangeCreateContract = contractParameter .unpack(ExchangeCreateContract.class); - contractJson = JSONObject.parseObject(JsonFormat.printToString(exchangeCreateContract)); + contractJson = JSONObject.parseObject(JsonFormat.printToString(exchangeCreateContract, + selfType)); break; case ExchangeInjectContract: ExchangeInjectContract exchangeInjectContract = contractParameter .unpack(ExchangeInjectContract.class); - contractJson = JSONObject.parseObject(JsonFormat.printToString(exchangeInjectContract)); + contractJson = JSONObject.parseObject(JsonFormat.printToString(exchangeInjectContract, + selfType)); break; case ExchangeWithdrawContract: ExchangeWithdrawContract exchangeWithdrawContract = contractParameter .unpack(ExchangeWithdrawContract.class); contractJson = JSONObject - .parseObject(JsonFormat.printToString(exchangeWithdrawContract)); + .parseObject(JsonFormat.printToString(exchangeWithdrawContract, selfType)); break; case ExchangeTransactionContract: ExchangeTransactionContract exchangeTransactionContract = contractParameter .unpack(ExchangeTransactionContract.class); contractJson = JSONObject - .parseObject(JsonFormat.printToString(exchangeTransactionContract)); + .parseObject(JsonFormat.printToString(exchangeTransactionContract, selfType)); + break; + case UpdateEnergyLimitContract: + UpdateEnergyLimitContract updateEnergyLimitContract = contractParameter + .unpack(UpdateEnergyLimitContract.class); + contractJson = JSONObject + .parseObject(JsonFormat.printToString(updateEnergyLimitContract, selfType)); break; case AccountPermissionUpdateContract: AccountPermissionUpdateContract accountPermissionUpdateContract = contractParameter .unpack(AccountPermissionUpdateContract.class); contractJson = JSONObject - .parseObject(JsonFormat.printToString(accountPermissionUpdateContract)); - break; - case UpdateSettingContract: - UpdateSettingContract updateSettingContract = contractParameter - .unpack(UpdateSettingContract.class); - contractJson = JSONObject.parseObject(JsonFormat.printToString(updateSettingContract)); + .parseObject(JsonFormat.printToString(accountPermissionUpdateContract, selfType)); break; - case UpdateEnergyLimitContract: - UpdateEnergyLimitContract updateEnergyLimitContract = contractParameter - .unpack(UpdateEnergyLimitContract.class); + case ClearABIContract: + Contract.ClearABIContract clearABIContract = contractParameter + .unpack(Contract.ClearABIContract.class); contractJson = JSONObject - .parseObject(JsonFormat.printToString(updateEnergyLimitContract)); + .parseObject(JsonFormat.printToString(clearABIContract, selfType)); break; // todo add other contract default: } JSONObject parameter = new JSONObject(); - parameter.put("value", contractJson); + parameter.put(VALUE, contractJson); parameter.put("type_url", contract.getParameterOrBuilder().getTypeUrl()); JSONObject jsonContract = new JSONObject(); jsonContract.put("parameter", parameter); jsonContract.put("type", contract.getType()); + if (contract.getPermissionId() > 0) { + jsonContract.put(PERMISSION_ID, contract.getPermissionId()); + } contracts.add(jsonContract); } catch (InvalidProtocolBufferException e) { logger.debug("InvalidProtocolBufferException: {}", e.getMessage()); @@ -338,7 +402,7 @@ public static JSONObject printTransactionToJSON(Transaction transaction) { return jsonTransaction; } - public static Transaction packTransaction(String strTransaction) { + public static Transaction packTransaction(String strTransaction, boolean selfType) { JSONObject jsonTransaction = JSONObject.parseObject(strTransaction); JSONObject rawData = jsonTransaction.getJSONObject("raw_data"); JSONArray contracts = new JSONArray(); @@ -354,213 +418,209 @@ public static Transaction packTransaction(String strTransaction) { case "AccountCreateContract": AccountCreateContract.Builder accountCreateContractBuilder = AccountCreateContract .newBuilder(); - JsonFormat.merge(parameter.getJSONObject("value").toJSONString(), - accountCreateContractBuilder); + JsonFormat.merge(parameter.getJSONObject(VALUE).toJSONString(), + accountCreateContractBuilder, selfType); any = Any.pack(accountCreateContractBuilder.build()); break; case "TransferContract": TransferContract.Builder transferContractBuilder = TransferContract.newBuilder(); - JsonFormat - .merge(parameter.getJSONObject("value").toJSONString(), transferContractBuilder); + JsonFormat.merge(parameter.getJSONObject(VALUE).toJSONString(), + transferContractBuilder, selfType); any = Any.pack(transferContractBuilder.build()); break; case "TransferAssetContract": TransferAssetContract.Builder transferAssetContractBuilder = TransferAssetContract .newBuilder(); - JsonFormat.merge(parameter.getJSONObject("value").toJSONString(), - transferAssetContractBuilder); + JsonFormat.merge(parameter.getJSONObject(VALUE).toJSONString(), + transferAssetContractBuilder, selfType); any = Any.pack(transferAssetContractBuilder.build()); break; case "VoteAssetContract": VoteAssetContract.Builder voteAssetContractBuilder = VoteAssetContract.newBuilder(); - JsonFormat - .merge(parameter.getJSONObject("value").toJSONString(), voteAssetContractBuilder); + JsonFormat.merge(parameter.getJSONObject(VALUE).toJSONString(), + voteAssetContractBuilder, selfType); any = Any.pack(voteAssetContractBuilder.build()); break; case "VoteWitnessContract": - VoteWitnessContract.Builder voteWitnessContractBuilder = VoteWitnessContract - .newBuilder(); - JsonFormat - .merge(parameter.getJSONObject("value").toJSONString(), voteWitnessContractBuilder); + VoteWitnessContract.Builder voteWitnessContractBuilder = + VoteWitnessContract.newBuilder(); + JsonFormat.merge(parameter.getJSONObject(VALUE).toJSONString(), + voteWitnessContractBuilder, selfType); any = Any.pack(voteWitnessContractBuilder.build()); break; case "WitnessCreateContract": WitnessCreateContract.Builder witnessCreateContractBuilder = WitnessCreateContract .newBuilder(); - JsonFormat.merge(parameter.getJSONObject("value").toJSONString(), - witnessCreateContractBuilder); + JsonFormat.merge(parameter.getJSONObject(VALUE).toJSONString(), + witnessCreateContractBuilder, selfType); any = Any.pack(witnessCreateContractBuilder.build()); break; case "AssetIssueContract": AssetIssueContract.Builder assetIssueContractBuilder = AssetIssueContract.newBuilder(); - JsonFormat - .merge(parameter.getJSONObject("value").toJSONString(), assetIssueContractBuilder); + JsonFormat.merge(parameter.getJSONObject(VALUE).toJSONString(), + assetIssueContractBuilder, selfType); any = Any.pack(assetIssueContractBuilder.build()); break; case "WitnessUpdateContract": WitnessUpdateContract.Builder witnessUpdateContractBuilder = WitnessUpdateContract .newBuilder(); - JsonFormat.merge(parameter.getJSONObject("value").toJSONString(), - witnessUpdateContractBuilder); + JsonFormat.merge(parameter.getJSONObject(VALUE).toJSONString(), + witnessUpdateContractBuilder, selfType); any = Any.pack(witnessUpdateContractBuilder.build()); break; case "ParticipateAssetIssueContract": ParticipateAssetIssueContract.Builder participateAssetIssueContractBuilder = ParticipateAssetIssueContract.newBuilder(); - JsonFormat.merge(parameter.getJSONObject("value").toJSONString(), - participateAssetIssueContractBuilder); + JsonFormat.merge(parameter.getJSONObject(VALUE).toJSONString(), + participateAssetIssueContractBuilder, selfType); any = Any.pack(participateAssetIssueContractBuilder.build()); break; case "AccountUpdateContract": AccountUpdateContract.Builder accountUpdateContractBuilder = AccountUpdateContract .newBuilder(); - JsonFormat.merge(parameter.getJSONObject("value").toJSONString(), - accountUpdateContractBuilder); + JsonFormat.merge(parameter.getJSONObject(VALUE).toJSONString(), + accountUpdateContractBuilder, selfType); any = Any.pack(accountUpdateContractBuilder.build()); break; case "FreezeBalanceContract": FreezeBalanceContract.Builder freezeBalanceContractBuilder = FreezeBalanceContract .newBuilder(); - JsonFormat.merge(parameter.getJSONObject("value").toJSONString(), - freezeBalanceContractBuilder); + JsonFormat.merge(parameter.getJSONObject(VALUE).toJSONString(), + freezeBalanceContractBuilder, selfType); any = Any.pack(freezeBalanceContractBuilder.build()); break; case "UnfreezeBalanceContract": UnfreezeBalanceContract.Builder unfreezeBalanceContractBuilder = UnfreezeBalanceContract .newBuilder(); - JsonFormat.merge(parameter.getJSONObject("value").toJSONString(), - unfreezeBalanceContractBuilder); + JsonFormat.merge(parameter.getJSONObject(VALUE).toJSONString(), + unfreezeBalanceContractBuilder, selfType); any = Any.pack(unfreezeBalanceContractBuilder.build()); break; - case "UnfreezeAssetContract": - UnfreezeAssetContract.Builder unfreezeAssetContractBuilder = UnfreezeAssetContract - .newBuilder(); - JsonFormat.merge(parameter.getJSONObject("value").toJSONString(), - unfreezeAssetContractBuilder); - any = Any.pack(unfreezeAssetContractBuilder.build()); - break; case "WithdrawBalanceContract": WithdrawBalanceContract.Builder withdrawBalanceContractBuilder = WithdrawBalanceContract .newBuilder(); - JsonFormat.merge(parameter.getJSONObject("value").toJSONString(), - withdrawBalanceContractBuilder); + JsonFormat.merge(parameter.getJSONObject(VALUE).toJSONString(), + withdrawBalanceContractBuilder, selfType); any = Any.pack(withdrawBalanceContractBuilder.build()); break; + case "UnfreezeAssetContract": + UnfreezeAssetContract.Builder unfreezeAssetContractBuilder = UnfreezeAssetContract + .newBuilder(); + JsonFormat.merge(parameter.getJSONObject(VALUE).toJSONString(), + unfreezeAssetContractBuilder, selfType); + any = Any.pack(unfreezeAssetContractBuilder.build()); + break; case "UpdateAssetContract": UpdateAssetContract.Builder updateAssetContractBuilder = UpdateAssetContract .newBuilder(); - JsonFormat - .merge(parameter.getJSONObject("value").toJSONString(), updateAssetContractBuilder); + JsonFormat.merge(parameter.getJSONObject(VALUE).toJSONString(), + updateAssetContractBuilder, selfType); any = Any.pack(updateAssetContractBuilder.build()); break; - case "SmartContract": - SmartContract.Builder smartContractBuilder = SmartContract.newBuilder(); - JsonFormat - .merge(parameter.getJSONObject("value").toJSONString(), smartContractBuilder); - any = Any.pack(smartContractBuilder.build()); + case "ProposalCreateContract": + ProposalCreateContract.Builder createContractBuilder = ProposalCreateContract + .newBuilder(); + JsonFormat.merge(parameter.getJSONObject(VALUE).toJSONString(), + createContractBuilder, selfType); + any = Any.pack(createContractBuilder.build()); break; - case "TriggerSmartContract": - TriggerSmartContract.Builder triggerSmartContractBuilder = TriggerSmartContract + case "ProposalApproveContract": + ProposalApproveContract.Builder approveContractBuilder = ProposalApproveContract .newBuilder(); - JsonFormat - .merge(parameter.getJSONObject("value").toJSONString(), - triggerSmartContractBuilder); - any = Any.pack(triggerSmartContractBuilder.build()); + JsonFormat.merge(parameter.getJSONObject(VALUE).toJSONString(), + approveContractBuilder, selfType); + any = Any.pack(approveContractBuilder.build()); + break; + case "ProposalDeleteContract": + ProposalDeleteContract.Builder deleteContractBuilder = ProposalDeleteContract + .newBuilder(); + JsonFormat.merge(parameter.getJSONObject(VALUE).toJSONString(), + deleteContractBuilder, selfType); + any = Any.pack(deleteContractBuilder.build()); + break; + case "SetAccountIdContract": + Contract.SetAccountIdContract.Builder setAccountid = Contract.SetAccountIdContract + .newBuilder(); + JsonFormat.merge(parameter.getJSONObject(VALUE).toJSONString(), + setAccountid, selfType); + any = Any.pack(setAccountid.build()); break; case "CreateSmartContract": CreateSmartContract.Builder createSmartContractBuilder = CreateSmartContract .newBuilder(); - JsonFormat - .merge(parameter.getJSONObject("value").toJSONString(), - createSmartContractBuilder); + JsonFormat.merge(parameter.getJSONObject(VALUE).toJSONString(), + createSmartContractBuilder, selfType); any = Any.pack(createSmartContractBuilder.build()); break; + case "TriggerSmartContract": + TriggerSmartContract.Builder triggerSmartContractBuilder = TriggerSmartContract + .newBuilder(); + JsonFormat.merge(parameter.getJSONObject(VALUE).toJSONString(), + triggerSmartContractBuilder, selfType); + any = Any.pack(triggerSmartContractBuilder.build()); + break; + case "UpdateSettingContract": + UpdateSettingContract.Builder updateSettingContractBuilder = UpdateSettingContract + .newBuilder(); + JsonFormat.merge(parameter.getJSONObject(VALUE).toJSONString(), + updateSettingContractBuilder, selfType); + any = Any.pack(updateSettingContractBuilder.build()); + break; case "ExchangeCreateContract": ExchangeCreateContract.Builder exchangeCreateContractBuilder = ExchangeCreateContract .newBuilder(); - JsonFormat - .merge(parameter.getJSONObject("value").toJSONString(), - exchangeCreateContractBuilder); + JsonFormat.merge(parameter.getJSONObject(VALUE).toJSONString(), + exchangeCreateContractBuilder, selfType); any = Any.pack(exchangeCreateContractBuilder.build()); break; case "ExchangeInjectContract": ExchangeInjectContract.Builder exchangeInjectContractBuilder = ExchangeInjectContract .newBuilder(); - JsonFormat - .merge(parameter.getJSONObject("value").toJSONString(), - exchangeInjectContractBuilder); + JsonFormat.merge(parameter.getJSONObject(VALUE).toJSONString(), + exchangeInjectContractBuilder, selfType); any = Any.pack(exchangeInjectContractBuilder.build()); break; case "ExchangeTransactionContract": ExchangeTransactionContract.Builder exchangeTransactionContractBuilder = ExchangeTransactionContract.newBuilder(); - JsonFormat - .merge(parameter.getJSONObject("value").toJSONString(), - exchangeTransactionContractBuilder); + JsonFormat.merge(parameter.getJSONObject(VALUE).toJSONString(), + exchangeTransactionContractBuilder, selfType); any = Any.pack(exchangeTransactionContractBuilder.build()); break; case "ExchangeWithdrawContract": ExchangeWithdrawContract.Builder exchangeWithdrawContractBuilder = ExchangeWithdrawContract.newBuilder(); - JsonFormat - .merge(parameter.getJSONObject("value").toJSONString(), - exchangeWithdrawContractBuilder); + JsonFormat.merge(parameter.getJSONObject(VALUE).toJSONString(), + exchangeWithdrawContractBuilder, selfType); any = Any.pack(exchangeWithdrawContractBuilder.build()); break; - case "ProposalCreateContract": - ProposalCreateContract.Builder ProposalCreateContractBuilder = ProposalCreateContract - .newBuilder(); - JsonFormat - .merge(parameter.getJSONObject("value").toJSONString(), - ProposalCreateContractBuilder); - any = Any.pack(ProposalCreateContractBuilder.build()); - break; - case "ProposalApproveContract": - ProposalApproveContract.Builder ProposalApproveContractBuilder = ProposalApproveContract - .newBuilder(); - JsonFormat - .merge(parameter.getJSONObject("value").toJSONString(), - ProposalApproveContractBuilder); - any = Any.pack(ProposalApproveContractBuilder.build()); - break; - case "ProposalDeleteContract": - ProposalDeleteContract.Builder ProposalDeleteContractBuilder = ProposalDeleteContract - .newBuilder(); - JsonFormat - .merge(parameter.getJSONObject("value").toJSONString(), - ProposalDeleteContractBuilder); - any = Any.pack(ProposalDeleteContractBuilder.build()); + case "UpdateEnergyLimitContract": + UpdateEnergyLimitContract.Builder updateEnergyLimitContractBuilder = + UpdateEnergyLimitContract.newBuilder(); + JsonFormat.merge(parameter.getJSONObject(VALUE).toJSONString(), + updateEnergyLimitContractBuilder, selfType); + any = Any.pack(updateEnergyLimitContractBuilder.build()); break; case "AccountPermissionUpdateContract": - AccountPermissionUpdateContract.Builder AccountPermissionUpdateContractBuilder = + AccountPermissionUpdateContract.Builder accountPermissionUpdateContractBuilder = AccountPermissionUpdateContract.newBuilder(); - JsonFormat - .merge(parameter.getJSONObject("value").toJSONString(), - AccountPermissionUpdateContractBuilder); - any = Any.pack(AccountPermissionUpdateContractBuilder.build()); - break; - case "UpdateSettingContract": - UpdateSettingContract.Builder UpdateSettingContractBuilder = UpdateSettingContract - .newBuilder(); - JsonFormat - .merge(parameter.getJSONObject("value").toJSONString(), - UpdateSettingContractBuilder); - any = Any.pack(UpdateSettingContractBuilder.build()); + JsonFormat.merge(parameter.getJSONObject(VALUE).toJSONString(), + accountPermissionUpdateContractBuilder, selfType); + any = Any.pack(accountPermissionUpdateContractBuilder.build()); break; - case "UpdateEnergyLimitContract": - UpdateEnergyLimitContract.Builder UpdateEnergyLimitContractBuilder = UpdateEnergyLimitContract - .newBuilder(); - JsonFormat - .merge(parameter.getJSONObject("value").toJSONString(), - UpdateEnergyLimitContractBuilder); - any = Any.pack(UpdateEnergyLimitContractBuilder.build()); + case "ClearABIContract": + Contract.ClearABIContract.Builder clearABIContract = + Contract.ClearABIContract.newBuilder(); + JsonFormat.merge(parameter.getJSONObject(VALUE).toJSONString(), clearABIContract, + selfType); + any = Any.pack(clearABIContract.build()); break; // todo add other contract default: } if (any != null) { String value = ByteArray.toHexString(any.getValue().toByteArray()); - parameter.put("value", value); + parameter.put(VALUE, value); contract.put("parameter", parameter); contracts.add(contract); } @@ -572,7 +632,7 @@ public static Transaction packTransaction(String strTransaction) { jsonTransaction.put("raw_data", rawData); Transaction.Builder transactionBuilder = Transaction.newBuilder(); try { - JsonFormat.merge(jsonTransaction.toJSONString(), transactionBuilder); + JsonFormat.merge(jsonTransaction.toJSONString(), transactionBuilder, selfType); return transactionBuilder.build(); } catch (ParseException e) { logger.debug("ParseException: {}", e.getMessage()); @@ -586,4 +646,84 @@ public static void checkBodySize(String body) throws Exception { throw new Exception("body size is too big, limit is " + args.getMaxMessageSize()); } } + + public static boolean getVisible(final HttpServletRequest request) { + boolean visible = false; + if (StringUtil.isNotBlank(request.getParameter(VISIBLE))) { + visible = Boolean.valueOf(request.getParameter(VISIBLE)); + } + return visible; + } + + public static boolean getVisiblePost(final String input) { + boolean visible = false; + JSONObject jsonObject = JSON.parseObject(input); + if (jsonObject.containsKey(VISIBLE)) { + visible = jsonObject.getBoolean(VISIBLE); + } + + return visible; + } + + public static String getHexAddress(final String address) { + if (address != null) { + byte[] addressByte = Wallet.decodeFromBase58Check(address); + return ByteArray.toHexString(addressByte); + } else { + return null; + } + } + + public static String getHexString(final String string) { + return ByteArray.toHexString(ByteString.copyFromUtf8(string).toByteArray()); + } + + public static Transaction setTransactionPermissionId(JSONObject jsonObject, + Transaction transaction) { + if (jsonObject.containsKey(PERMISSION_ID)) { + int permissionId = jsonObject.getInteger(PERMISSION_ID); + if (permissionId > 0) { + Transaction.raw.Builder raw = transaction.getRawData().toBuilder(); + Transaction.Contract.Builder contract = raw.getContract(0).toBuilder() + .setPermissionId(permissionId); + raw.clearContract(); + raw.addContract(contract); + return transaction.toBuilder().setRawData(raw).build(); + } + } + return transaction; + } + + public static boolean getVisibleOnlyForSign(JSONObject jsonObject) { + boolean visible = false; + if (jsonObject.containsKey(VISIBLE)) { + visible = jsonObject.getBoolean(VISIBLE); + } else if (jsonObject.getJSONObject(TRANSACTION).containsKey(VISIBLE)) { + visible = jsonObject.getJSONObject(TRANSACTION).getBoolean(VISIBLE); + } + return visible; + } + + public static String parseMethod(String methodSign, String input) { + byte[] selector = new byte[4]; + System.arraycopy(Hash.sha3(methodSign.getBytes()), 0, selector, 0, 4); + //System.out.println(methodSign + ":" + Hex.toHexString(selector)); + if (StringUtils.isNullOrEmpty(input)) { + return Hex.toHexString(selector); + } + + return Hex.toHexString(selector) + input; + } + + public static long getJsonLongValue(final JSONObject jsonObject, final String key) { + return getJsonLongValue(jsonObject, key, false); + } + + public static long getJsonLongValue(JSONObject jsonObject, String key, boolean required) { + BigDecimal bigDecimal = jsonObject.getBigDecimal(key); + if (required && bigDecimal == null) { + throw new InvalidParameterException("key [" + key + "] not exist"); + } + return (bigDecimal == null) ? 0L : bigDecimal.longValueExact(); + } } diff --git a/src/main/java/org/tron/core/services/http/ValidateAddressServlet.java b/src/main/java/org/tron/core/services/http/ValidateAddressServlet.java index 55f24a40187..04ffc18a1ff 100644 --- a/src/main/java/org/tron/core/services/http/ValidateAddressServlet.java +++ b/src/main/java/org/tron/core/services/http/ValidateAddressServlet.java @@ -2,12 +2,14 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; + import java.io.IOException; import java.util.Base64; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.tron.common.utils.ByteArray; diff --git a/src/main/java/org/tron/core/services/http/VoteWitnessAccountServlet.java b/src/main/java/org/tron/core/services/http/VoteWitnessAccountServlet.java index c6600fdb911..e24d6ab718f 100644 --- a/src/main/java/org/tron/core/services/http/VoteWitnessAccountServlet.java +++ b/src/main/java/org/tron/core/services/http/VoteWitnessAccountServlet.java @@ -1,5 +1,6 @@ package org.tron.core.services.http; +import com.alibaba.fastjson.JSONObject; import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; @@ -30,11 +31,14 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String contract = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(contract); + boolean visible = Util.getVisiblePost(contract); VoteWitnessContract.Builder build = VoteWitnessContract.newBuilder(); - JsonFormat.merge(contract, build); + JsonFormat.merge(contract, build, visible); Transaction tx = wallet .createTransactionCapsule(build.build(), ContractType.VoteWitnessContract).getInstance(); - response.getWriter().println(Util.printTransaction(tx)); + JSONObject jsonObject = JSONObject.parseObject(contract); + tx = Util.setTransactionPermissionId(jsonObject, tx); + response.getWriter().println(Util.printCreateTransaction(tx, visible)); } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); try { diff --git a/src/main/java/org/tron/core/services/http/WithdrawBalanceServlet.java b/src/main/java/org/tron/core/services/http/WithdrawBalanceServlet.java index 46006796cee..c4b5f57ca1e 100644 --- a/src/main/java/org/tron/core/services/http/WithdrawBalanceServlet.java +++ b/src/main/java/org/tron/core/services/http/WithdrawBalanceServlet.java @@ -1,5 +1,6 @@ package org.tron.core.services.http; +import com.alibaba.fastjson.JSONObject; import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; @@ -30,12 +31,15 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String contract = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(contract); + boolean visible = Util.getVisiblePost(contract); WithdrawBalanceContract.Builder build = WithdrawBalanceContract.newBuilder(); - JsonFormat.merge(contract, build); + JsonFormat.merge(contract, build, visible); Transaction tx = wallet .createTransactionCapsule(build.build(), ContractType.WithdrawBalanceContract) .getInstance(); - response.getWriter().println(Util.printTransaction(tx)); + JSONObject jsonObject = JSONObject.parseObject(contract); + tx = Util.setTransactionPermissionId(jsonObject, tx); + response.getWriter().println(Util.printCreateTransaction(tx, visible)); } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); try { diff --git a/src/main/java/org/tron/core/services/http/solidity/GetTransactionByIdSolidityServlet.java b/src/main/java/org/tron/core/services/http/solidity/GetTransactionByIdSolidityServlet.java index bc4915f7c60..51490500741 100644 --- a/src/main/java/org/tron/core/services/http/solidity/GetTransactionByIdSolidityServlet.java +++ b/src/main/java/org/tron/core/services/http/solidity/GetTransactionByIdSolidityServlet.java @@ -1,11 +1,13 @@ package org.tron.core.services.http.solidity; import com.google.protobuf.ByteString; + import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -16,6 +18,7 @@ import org.tron.core.services.http.Util; import org.tron.protos.Protocol.Transaction; + @Component @Slf4j(topic = "API") public class GetTransactionByIdSolidityServlet extends HttpServlet { @@ -25,11 +28,12 @@ public class GetTransactionByIdSolidityServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { + boolean visible = Util.getVisible(request); String input = request.getParameter("value"); Transaction reply = wallet .getTransactionById(ByteString.copyFrom(ByteArray.fromHexString(input))); if (reply != null) { - response.getWriter().println(Util.printTransaction(reply)); + response.getWriter().println(Util.printTransaction(reply, visible)); } else { response.getWriter().println("{}"); } @@ -48,11 +52,12 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String input = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); + boolean visible = Util.getVisiblePost(input); BytesMessage.Builder build = BytesMessage.newBuilder(); - JsonFormat.merge(input, build); + JsonFormat.merge(input, build, visible); Transaction reply = wallet.getTransactionById(build.build().getValue()); if (reply != null) { - response.getWriter().println(Util.printTransaction(reply)); + response.getWriter().println(Util.printTransaction(reply, visible)); } else { response.getWriter().println("{}"); } diff --git a/src/main/java/org/tron/core/services/http/solidity/GetTransactionInfoByIdSolidityServlet.java b/src/main/java/org/tron/core/services/http/solidity/GetTransactionInfoByIdSolidityServlet.java index d0cd7b743e3..9facb3f0de9 100644 --- a/src/main/java/org/tron/core/services/http/solidity/GetTransactionInfoByIdSolidityServlet.java +++ b/src/main/java/org/tron/core/services/http/solidity/GetTransactionInfoByIdSolidityServlet.java @@ -1,11 +1,13 @@ package org.tron.core.services.http.solidity; import com.google.protobuf.ByteString; + import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -27,13 +29,14 @@ public class GetTransactionInfoByIdSolidityServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) { try { + boolean visible = Util.getVisible(request); String input = request.getParameter("value"); TransactionInfo transInfo = wallet.getTransactionInfoById(ByteString.copyFrom( ByteArray.fromHexString(input))); if (transInfo == null) { response.getWriter().println("{}"); } else { - response.getWriter().println(JsonFormat.printToString(transInfo)); + response.getWriter().println(JsonFormat.printToString(transInfo, visible)); } } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); @@ -51,13 +54,14 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String input = request.getReader().lines() .collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); + boolean visible = Util.getVisiblePost(input); BytesMessage.Builder build = BytesMessage.newBuilder(); - JsonFormat.merge(input, build); + JsonFormat.merge(input, build, visible); TransactionInfo transInfo = wallet.getTransactionInfoById(build.build().getValue()); if (transInfo == null) { response.getWriter().println("{}"); } else { - response.getWriter().println(JsonFormat.printToString(transInfo)); + response.getWriter().println(JsonFormat.printToString(transInfo, visible)); } } catch (Exception e) { logger.debug("Exception: {}", e.getMessage()); diff --git a/src/main/java/org/tron/core/services/http/solidity/GetTransactionsFromThisServlet.java b/src/main/java/org/tron/core/services/http/solidity/GetTransactionsFromThisServlet.java index 0bec27ff854..dd174794d65 100644 --- a/src/main/java/org/tron/core/services/http/solidity/GetTransactionsFromThisServlet.java +++ b/src/main/java/org/tron/core/services/http/solidity/GetTransactionsFromThisServlet.java @@ -15,6 +15,7 @@ import org.tron.core.services.http.JsonFormat; import org.tron.core.services.http.Util; + @Component @Slf4j(topic = "API") public class GetTransactionsFromThisServlet extends HttpServlet { @@ -27,15 +28,16 @@ protected void doPost(HttpServletRequest req, HttpServletResponse resp) { try { String input = req.getReader().lines().collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); + boolean visible = Util.getVisiblePost(input); AccountPaginated.Builder builder = AccountPaginated.newBuilder(); - JsonFormat.merge(input, builder); + JsonFormat.merge(input, builder, visible); AccountPaginated accountPaginated = builder.build(); ByteString thisAddress = accountPaginated.getAccount().getAddress(); long offset = accountPaginated.getOffset(); long limit = accountPaginated.getLimit(); if (thisAddress != null && offset >= 0 && limit >= 0) { TransactionList list = walletSolidity.getTransactionsFromThis(thisAddress, offset, limit); - resp.getWriter().println(Util.printTransactionList(list)); + resp.getWriter().println(Util.printTransactionList(list, visible)); } else { resp.getWriter().print("{}"); } diff --git a/src/main/java/org/tron/core/services/http/solidity/GetTransactionsToThisServlet.java b/src/main/java/org/tron/core/services/http/solidity/GetTransactionsToThisServlet.java index 84523098dc1..b42c8b6f549 100644 --- a/src/main/java/org/tron/core/services/http/solidity/GetTransactionsToThisServlet.java +++ b/src/main/java/org/tron/core/services/http/solidity/GetTransactionsToThisServlet.java @@ -1,11 +1,13 @@ package org.tron.core.services.http.solidity; import com.google.protobuf.ByteString; + import java.io.IOException; import java.util.stream.Collectors; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -15,6 +17,7 @@ import org.tron.core.services.http.JsonFormat; import org.tron.core.services.http.Util; + @Component @Slf4j(topic = "API") public class GetTransactionsToThisServlet extends HttpServlet { @@ -27,15 +30,16 @@ protected void doPost(HttpServletRequest req, HttpServletResponse resp) { try { String input = req.getReader().lines().collect(Collectors.joining(System.lineSeparator())); Util.checkBodySize(input); + boolean visible = Util.getVisiblePost(input); AccountPaginated.Builder builder = AccountPaginated.newBuilder(); - JsonFormat.merge(input, builder); + JsonFormat.merge(input, builder, visible); AccountPaginated accountPaginated = builder.build(); ByteString toAddress = accountPaginated.getAccount().getAddress(); long offset = accountPaginated.getOffset(); long limit = accountPaginated.getLimit(); if (toAddress != null && offset >= 0 && limit >= 0) { TransactionList list = walletSolidity.getTransactionsToThis(toAddress, offset, limit); - resp.getWriter().println(Util.printTransactionList(list)); + resp.getWriter().println(Util.printTransactionList(list, visible)); } else { resp.getWriter().print("{}"); } diff --git a/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java b/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java index 2840c606814..8d25d330831 100644 --- a/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java +++ b/src/main/java/org/tron/core/services/http/solidity/SolidityNodeHttpApiService.java @@ -1,6 +1,7 @@ package org.tron.core.services.http.solidity; import lombok.extern.slf4j.Slf4j; +import org.eclipse.jetty.server.ConnectionLimit; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; @@ -8,21 +9,8 @@ import org.springframework.stereotype.Component; import org.tron.common.application.Service; import org.tron.core.config.args.Args; -import org.tron.core.services.http.GetAccountServlet; -import org.tron.core.services.http.GetAssetIssueByIdServlet; -import org.tron.core.services.http.GetAssetIssueByNameServlet; -import org.tron.core.services.http.GetAssetIssueListByNameServlet; -import org.tron.core.services.http.GetAssetIssueListServlet; -import org.tron.core.services.http.GetBlockByNumServlet; -import org.tron.core.services.http.GetDelegatedResourceAccountIndexServlet; -import org.tron.core.services.http.GetDelegatedResourceServlet; -import org.tron.core.services.http.GetExchangeByIdServlet; -import org.tron.core.services.http.GetNodeInfoServlet; -import org.tron.core.services.http.GetNowBlockServlet; -import org.tron.core.services.http.GetPaginatedAssetIssueListServlet; -import org.tron.core.services.http.GetTransactionCountByBlockNumServlet; -import org.tron.core.services.http.ListExchangesServlet; -import org.tron.core.services.http.ListWitnessesServlet; +import org.tron.core.services.http.*; + @Component @Slf4j(topic = "API") @@ -35,7 +23,6 @@ public class SolidityNodeHttpApiService implements Service { @Autowired private GetAccountServlet getAccountServlet; - @Autowired private GetTransactionByIdSolidityServlet getTransactionByIdServlet; @Autowired @@ -71,9 +58,16 @@ public class SolidityNodeHttpApiService implements Service { private GetNowBlockServlet getNowBlockServlet; @Autowired private GetBlockByNumServlet getBlockByNumServlet; - @Autowired private GetNodeInfoServlet getNodeInfoServlet; + @Autowired + private GetAccountByIdServlet getAccountByIdServlet; + @Autowired + private GetBlockByIdServlet getBlockByIdServlet; + @Autowired + private GetBlockByLimitNextServlet getBlockByLimitNextServlet; + @Autowired + private GetBlockByLatestNumServlet getBlockByLatestNumServlet; @Override public void init() { @@ -114,12 +108,24 @@ public void start() { context.addServlet(new ServletHolder(getDelegatedResourceAccountIndexServlet), "/walletsolidity/getdelegatedresourceaccountindex"); context - .addServlet(new ServletHolder(getExchangeByIdServlet), "/walletsolidity/getexchangebyid"); - context.addServlet(new ServletHolder(listExchangesServlet), "/walletsolidity/listexchanges"); + .addServlet(new ServletHolder(getExchangeByIdServlet), + "/walletsolidity/getexchangebyid"); + context.addServlet(new ServletHolder(listExchangesServlet), + "/walletsolidity/listexchanges"); + + context.addServlet(new ServletHolder(getAccountByIdServlet), + "/walletsolidity/getaccountbyid"); + context.addServlet(new ServletHolder(getBlockByIdServlet), + "/walletsolidity/getblockbyid"); + context.addServlet(new ServletHolder(getBlockByLimitNextServlet), + "/walletsolidity/getblockbylimitnext"); + context.addServlet(new ServletHolder(getBlockByLatestNumServlet), + "/walletsolidity/getblockbylatestnum"); // only for SolidityNode context.addServlet(new ServletHolder(getTransactionByIdServlet), "/walletsolidity/gettransactionbyid"); + context .addServlet(new ServletHolder(getTransactionInfoByIdServlet), "/walletsolidity/gettransactioninfobyid"); @@ -137,6 +143,10 @@ public void start() { } context.addServlet(new ServletHolder(getNodeInfoServlet), "/wallet/getnodeinfo"); + int maxHttpConnectNumber = Args.getInstance().getMaxHttpConnectNumber(); + if (maxHttpConnectNumber > 0) { + server.addBean(new ConnectionLimit(maxHttpConnectNumber, server)); + } server.start(); } catch (Exception e) { diff --git a/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetAccountByIdOnSolidityServlet.java b/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetAccountByIdOnSolidityServlet.java new file mode 100644 index 00000000000..ce47e679d0a --- /dev/null +++ b/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetAccountByIdOnSolidityServlet.java @@ -0,0 +1,25 @@ +package org.tron.core.services.interfaceOnSolidity.http; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.services.http.GetAccountByIdServlet; +import org.tron.core.services.interfaceOnSolidity.WalletOnSolidity; + +@Component +@Slf4j(topic = "API") +public class GetAccountByIdOnSolidityServlet extends GetAccountByIdServlet { + + @Autowired + private WalletOnSolidity walletOnSolidity; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + walletOnSolidity.futureGet(() -> super.doGet(request, response)); + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + walletOnSolidity.futureGet(() -> super.doPost(request, response)); + } +} diff --git a/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetBlockByIdOnSolidityServlet.java b/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetBlockByIdOnSolidityServlet.java new file mode 100644 index 00000000000..16192e2f484 --- /dev/null +++ b/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetBlockByIdOnSolidityServlet.java @@ -0,0 +1,25 @@ +package org.tron.core.services.interfaceOnSolidity.http; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.services.http.GetBlockByIdServlet; +import org.tron.core.services.interfaceOnSolidity.WalletOnSolidity; + +@Component +@Slf4j(topic = "API") +public class GetBlockByIdOnSolidityServlet extends GetBlockByIdServlet { + + @Autowired + private WalletOnSolidity walletOnSolidity; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + walletOnSolidity.futureGet(() -> super.doGet(request, response)); + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + walletOnSolidity.futureGet(() -> super.doPost(request, response)); + } +} diff --git a/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetBlockByLatestNumOnSolidityServlet.java b/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetBlockByLatestNumOnSolidityServlet.java new file mode 100644 index 00000000000..34b5f37dcf5 --- /dev/null +++ b/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetBlockByLatestNumOnSolidityServlet.java @@ -0,0 +1,26 @@ +package org.tron.core.services.interfaceOnSolidity.http; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.services.http.GetBlockByLatestNumServlet; +import org.tron.core.services.interfaceOnSolidity.WalletOnSolidity; + +@Component +@Slf4j(topic = "API") +public class GetBlockByLatestNumOnSolidityServlet extends GetBlockByLatestNumServlet { + + @Autowired + private WalletOnSolidity walletOnSolidity; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + walletOnSolidity.futureGet(() -> super.doGet(request, response)); + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + walletOnSolidity.futureGet(() -> super.doPost(request, response)); + } + +} diff --git a/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetBlockByLimitNextOnSolidityServlet.java b/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetBlockByLimitNextOnSolidityServlet.java new file mode 100644 index 00000000000..36de59a9e7e --- /dev/null +++ b/src/main/java/org/tron/core/services/interfaceOnSolidity/http/GetBlockByLimitNextOnSolidityServlet.java @@ -0,0 +1,25 @@ +package org.tron.core.services.interfaceOnSolidity.http; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.services.http.GetBlockByLimitNextServlet; +import org.tron.core.services.interfaceOnSolidity.WalletOnSolidity; + +@Component +@Slf4j(topic = "API") +public class GetBlockByLimitNextOnSolidityServlet extends GetBlockByLimitNextServlet { + + @Autowired + private WalletOnSolidity walletOnSolidity; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + walletOnSolidity.futureGet(() -> super.doGet(request, response)); + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + walletOnSolidity.futureGet(() -> super.doPost(request, response)); + } +} diff --git a/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java b/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java index c45fda6f582..83ba4d13141 100644 --- a/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java +++ b/src/main/java/org/tron/core/services/interfaceOnSolidity/http/solidity/HttpApiOnSolidityService.java @@ -1,27 +1,14 @@ package org.tron.core.services.interfaceOnSolidity.http.solidity; import lombok.extern.slf4j.Slf4j; +import org.eclipse.jetty.server.ConnectionLimit; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.springframework.beans.factory.annotation.Autowired; import org.tron.common.application.Service; import org.tron.core.config.args.Args; -import org.tron.core.services.interfaceOnSolidity.http.GetAccountOnSolidityServlet; -import org.tron.core.services.interfaceOnSolidity.http.GetAssetIssueByIdOnSolidityServlet; -import org.tron.core.services.interfaceOnSolidity.http.GetAssetIssueByNameOnSolidityServlet; -import org.tron.core.services.interfaceOnSolidity.http.GetAssetIssueListByNameOnSolidityServlet; -import org.tron.core.services.interfaceOnSolidity.http.GetAssetIssueListOnSolidityServlet; -import org.tron.core.services.interfaceOnSolidity.http.GetBlockByNumOnSolidityServlet; -import org.tron.core.services.interfaceOnSolidity.http.GetDelegatedResourceAccountIndexOnSolidityServlet; -import org.tron.core.services.interfaceOnSolidity.http.GetDelegatedResourceOnSolidityServlet; -import org.tron.core.services.interfaceOnSolidity.http.GetExchangeByIdOnSolidityServlet; -import org.tron.core.services.interfaceOnSolidity.http.GetNodeInfoOnSolidityServlet; -import org.tron.core.services.interfaceOnSolidity.http.GetNowBlockOnSolidityServlet; -import org.tron.core.services.interfaceOnSolidity.http.GetPaginatedAssetIssueListOnSolidityServlet; -import org.tron.core.services.interfaceOnSolidity.http.GetTransactionCountByBlockNumOnSolidityServlet; -import org.tron.core.services.interfaceOnSolidity.http.ListExchangesOnSolidityServlet; -import org.tron.core.services.interfaceOnSolidity.http.ListWitnessesOnSolidityServlet; +import org.tron.core.services.interfaceOnSolidity.http.*; @Slf4j(topic = "API") public class HttpApiOnSolidityService implements Service { @@ -37,8 +24,6 @@ public class HttpApiOnSolidityService implements Service { private GetTransactionByIdOnSolidityServlet getTransactionByIdOnSolidityServlet; @Autowired private GetTransactionInfoByIdOnSolidityServlet getTransactionInfoByIdOnSolidityServlet; - - @Autowired private ListWitnessesOnSolidityServlet listWitnessesOnSolidityServlet; @Autowired @@ -56,19 +41,29 @@ public class HttpApiOnSolidityService implements Service { @Autowired private GetDelegatedResourceOnSolidityServlet getDelegatedResourceOnSolidityServlet; @Autowired - private GetDelegatedResourceAccountIndexOnSolidityServlet getDelegatedResourceAccountIndexOnSolidityServlet; + private GetDelegatedResourceAccountIndexOnSolidityServlet + getDelegatedResourceAccountIndexOnSolidityServlet; @Autowired private GetExchangeByIdOnSolidityServlet getExchangeByIdOnSolidityServlet; @Autowired private ListExchangesOnSolidityServlet listExchangesOnSolidityServlet; @Autowired - private GetTransactionCountByBlockNumOnSolidityServlet getTransactionCountByBlockNumOnSolidityServlet; + private GetTransactionCountByBlockNumOnSolidityServlet + getTransactionCountByBlockNumOnSolidityServlet; @Autowired private GetAssetIssueByNameOnSolidityServlet getAssetIssueByNameOnSolidityServlet; @Autowired private GetAssetIssueByIdOnSolidityServlet getAssetIssueByIdOnSolidityServlet; @Autowired private GetAssetIssueListByNameOnSolidityServlet getAssetIssueListByNameOnSolidityServlet; + @Autowired + private GetAccountByIdOnSolidityServlet getAccountByIdOnSolidityServlet; + @Autowired + private GetBlockByIdOnSolidityServlet getBlockByIdOnSolidityServlet; + @Autowired + private GetBlockByLimitNextOnSolidityServlet getBlockByLimitNextOnSolidityServlet; + @Autowired + private GetBlockByLatestNumOnSolidityServlet getBlockByLatestNumOnSolidityServlet; @Override public void init() { @@ -114,6 +109,14 @@ public void start() { "/walletsolidity/getexchangebyid"); context.addServlet(new ServletHolder(listExchangesOnSolidityServlet), "/walletsolidity/listexchanges"); + context.addServlet(new ServletHolder(getAccountByIdOnSolidityServlet), + "/walletsolidity/getaccountbyid"); + context.addServlet(new ServletHolder(getBlockByIdOnSolidityServlet), + "/walletsolidity/getblockbyid"); + context.addServlet(new ServletHolder(getBlockByLimitNextOnSolidityServlet), + "/walletsolidity/getblockbylimitnext"); + context.addServlet(new ServletHolder(getBlockByLatestNumOnSolidityServlet), + "/walletsolidity/getblockbylatestnum"); // only for SolidityNode context.addServlet(new ServletHolder(getTransactionByIdOnSolidityServlet), @@ -121,12 +124,16 @@ public void start() { context .addServlet(new ServletHolder(getTransactionInfoByIdOnSolidityServlet), "/walletsolidity/gettransactioninfobyid"); + context .addServlet(new ServletHolder(getTransactionCountByBlockNumOnSolidityServlet), "/walletsolidity/gettransactioncountbyblocknum"); context.addServlet(new ServletHolder(getNodeInfoOnSolidityServlet), "/wallet/getnodeinfo"); - + int maxHttpConnectNumber = Args.getInstance().getMaxHttpConnectNumber(); + if (maxHttpConnectNumber > 0) { + server.addBean(new ConnectionLimit(maxHttpConnectNumber, server)); + } server.start(); } catch (Exception e) { logger.debug("IOException: {}", e.getMessage()); diff --git a/src/main/java/org/tron/core/trie/Trie.java b/src/main/java/org/tron/core/trie/Trie.java new file mode 100644 index 00000000000..c886d577c59 --- /dev/null +++ b/src/main/java/org/tron/core/trie/Trie.java @@ -0,0 +1,24 @@ +package org.tron.core.trie; + +/** + * + */ +public interface Trie { + + byte[] getRootHash(); + + void setRoot(byte[] root); + + /** + * Recursively delete all nodes from root + */ + void clear(); + + void put(byte[] key, V val); + + V get(byte[] key); + + void delete(byte[] key); + + boolean flush(); +} diff --git a/src/main/java/org/tron/core/trie/TrieImpl.java b/src/main/java/org/tron/core/trie/TrieImpl.java new file mode 100644 index 00000000000..204258da761 --- /dev/null +++ b/src/main/java/org/tron/core/trie/TrieImpl.java @@ -0,0 +1,979 @@ +package org.tron.core.trie; + +import static org.apache.commons.lang3.concurrent.ConcurrentUtils.constantFuture; +import static org.tron.common.crypto.Hash.EMPTY_TRIE_HASH; +import static org.tron.common.utils.ByteUtil.EMPTY_BYTE_ARRAY; +import static org.tron.common.utils.ByteUtil.toHexString; +import static org.tron.core.capsule.utils.RLP.EMPTY_ELEMENT_RLP; +import static org.tron.core.capsule.utils.RLP.encodeElement; +import static org.tron.core.capsule.utils.RLP.encodeList; + +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map.Entry; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import org.apache.commons.lang3.text.StrBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.spongycastle.util.encoders.Hex; +import org.tron.common.crypto.Hash; +import org.tron.core.capsule.BytesCapsule; +import org.tron.core.capsule.utils.FastByteComparisons; +import org.tron.core.capsule.utils.RLP; +import org.tron.core.db2.common.ConcurrentHashDB; +import org.tron.core.db2.common.DB; + +/** + * + */ +public class TrieImpl implements Trie { + + private final static Object NULL_NODE = new Object(); + private final static int MIN_BRANCHES_CONCURRENTLY = 3; + private static ExecutorService executor; + + private static final Logger logger = LoggerFactory.getLogger(TrieImpl.class); + + public static ExecutorService getExecutor() { + if (executor == null) { + executor = Executors.newFixedThreadPool(4, + new ThreadFactoryBuilder().setNameFormat("trie-calc-thread-%d").build()); + } + return executor; + } + + public enum NodeType { + BranchNode, + KVNodeValue, + KVNodeNode + } + + public final class Node { + + byte[] hash = null; + private byte[] rlp = null; + private RLP.LList parsedRlp = null; + private boolean dirty = false; + private NodeType nodeType; + + private Object[] children = null; + + // new empty BranchNode + public Node() { + children = new Object[17]; + dirty = true; + } + + // new KVNode with key and (value or node) + public Node(TrieKey key, Object valueOrNode) { + this(new Object[]{key, valueOrNode}); + dirty = true; + } + + // new Node with hash or RLP + public Node(byte[] hashOrRlp) { + if (hashOrRlp.length == 32) { + this.hash = hashOrRlp; + } else { + this.rlp = hashOrRlp; + } + } + + private Node(RLP.LList parsedRlp) { + this.parsedRlp = parsedRlp; + this.rlp = parsedRlp.getEncoded(); + } + + private Node(Object[] children) { + this.children = children; + } + + public Node(int length) { + this.children = new Object[length]; + } + + public boolean resolveCheck() { + if (rlp != null || parsedRlp != null || hash == null) { + return true; + } + rlp = getHash(hash); + return rlp != null; + } + + private void resolve() { + if (!resolveCheck()) { + logger.error("Invalid Trie state, can't resolve hash " + toHexString(hash)); + throw new RuntimeException("Invalid Trie state, can't resolve hash " + toHexString(hash)); + } + } + + public byte[] encode() { + return encode(1, true); + } + + private byte[] encode(final int depth, boolean forceHash) { + if (!dirty) { + return hash != null ? encodeElement(hash) : rlp; + } else { + NodeType type = getType(); + byte[] ret; + if (type == NodeType.BranchNode) { + if (depth == 1 && async) { + // parallelize encode() on the first trie level only and if there are at least + // MIN_BRANCHES_CONCURRENTLY branches are modified + final Object[] encoded = new Object[17]; + int encodeCnt = 0; + for (int i = 0; i < 16; i++) { + final Node child = branchNodeGetChild(i); + if (child == null) { + encoded[i] = EMPTY_ELEMENT_RLP; + } else if (!child.dirty) { + encoded[i] = child.encode(depth + 1, false); + } else { + encodeCnt++; + } + } + for (int i = 0; i < 16; i++) { + if (encoded[i] == null) { + final Node child = branchNodeGetChild(i); + if (child == null) { + continue; + } + if (encodeCnt >= MIN_BRANCHES_CONCURRENTLY) { + encoded[i] = getExecutor().submit(() -> child.encode(depth + 1, false)); + } else { + encoded[i] = child.encode(depth + 1, false); + } + } + } + byte[] value = branchNodeGetValue(); + encoded[16] = constantFuture(encodeElement(value)); + try { + ret = encodeRlpListFutures(encoded); + } catch (Exception e) { + throw new RuntimeException(e); + } + } else { + byte[][] encoded = new byte[17][]; + for (int i = 0; i < 16; i++) { + Node child = branchNodeGetChild(i); + encoded[i] = child == null ? EMPTY_ELEMENT_RLP : child.encode(depth + 1, false); + } + byte[] value = branchNodeGetValue(); + encoded[16] = encodeElement(value); + ret = encodeList(encoded); + } + } else if (type == NodeType.KVNodeNode) { + ret = encodeList(encodeElement(kvNodeGetKey().toPacked()), + kvNodeGetChildNode().encode(depth + 1, false)); + } else { + byte[] value = kvNodeGetValue(); + ret = encodeList(encodeElement(kvNodeGetKey().toPacked()), + encodeElement(value == null ? EMPTY_BYTE_ARRAY : value)); + } + if (hash != null) { + deleteHash(hash); + } + dirty = false; + if (ret.length < 32 && !forceHash) { + rlp = ret; + return ret; + } else { + hash = Hash.sha3(ret); + addHash(hash, ret); + return encodeElement(hash); + } + } + } + + @SafeVarargs + private final byte[] encodeRlpListFutures(Object... list) + throws ExecutionException, InterruptedException { + byte[][] vals = new byte[list.length][]; + for (int i = 0; i < list.length; i++) { + if (list[i] instanceof Future) { + vals[i] = ((Future) list[i]).get(); + } else { + vals[i] = (byte[]) list[i]; + } + } + return encodeList(vals); + } + + private void parse() { + if (children != null) { + return; + } + resolve(); + + RLP.LList list = parsedRlp == null ? RLP.decodeLazyList(rlp) : parsedRlp; + + if (list != null && list.size() == 2) { + children = new Object[2]; + TrieKey key = TrieKey.fromPacked(list.getBytes(0)); + children[0] = key; + if (key.isTerminal()) { + children[1] = list.getBytes(1); + } else { + children[1] = list.isList(1) ? new Node(list.getList(1)) : new Node(list.getBytes(1)); + } + } else { + children = new Object[17]; + parsedRlp = list; + } + } + + public Node branchNodeGetChild(int hex) { + parse(); + assert getType() == NodeType.BranchNode; + Object n = children[hex]; + if (n == null && parsedRlp != null) { + if (parsedRlp.isList(hex)) { + n = new Node(parsedRlp.getList(hex)); + } else { + byte[] bytes = parsedRlp.getBytes(hex); + if (bytes.length == 0) { + n = NULL_NODE; + } else { + n = new Node(bytes); + } + } + children[hex] = n; + } + return n == NULL_NODE ? null : (Node) n; + } + + public Node branchNodeSetChild(int hex, Node node) { + parse(); + assert getType() == NodeType.BranchNode; + children[hex] = node == null ? NULL_NODE : node; + dirty = true; + return this; + } + + public byte[] branchNodeGetValue() { + parse(); + assert getType() == NodeType.BranchNode; + Object n = children[16]; + if (n == null && parsedRlp != null) { + byte[] bytes = parsedRlp.getBytes(16); + if (bytes.length == 0) { + n = NULL_NODE; + } else { + n = bytes; + } + children[16] = n; + } + return n == NULL_NODE ? null : (byte[]) n; + } + + public Node branchNodeSetValue(byte[] val) { + parse(); + assert getType() == NodeType.BranchNode; + children[16] = val == null ? NULL_NODE : val; + dirty = true; + return this; + } + + public int branchNodeCompactIdx() { + parse(); + assert getType() == NodeType.BranchNode; + int cnt = 0; + int idx = -1; + for (int i = 0; i < 16; i++) { + if (branchNodeGetChild(i) != null) { + cnt++; + idx = i; + if (cnt > 1) { + return -1; + } + } + } + return cnt > 0 ? idx : (branchNodeGetValue() == null ? -1 : 16); + } + + public boolean branchNodeCanCompact() { + parse(); + assert getType() == NodeType.BranchNode; + int cnt = 0; + for (int i = 0; i < 16; i++) { + cnt += branchNodeGetChild(i) == null ? 0 : 1; + if (cnt > 1) { + return false; + } + } + return cnt == 0 || branchNodeGetValue() == null; + } + + public TrieKey kvNodeGetKey() { + parse(); + assert getType() != NodeType.BranchNode; + return (TrieKey) children[0]; + } + + public Node kvNodeGetChildNode() { + parse(); + assert getType() == NodeType.KVNodeNode; + return (Node) children[1]; + } + + public byte[] kvNodeGetValue() { + parse(); + assert getType() == NodeType.KVNodeValue; + return (byte[]) children[1]; + } + + public Node kvNodeSetValue(byte[] value) { + parse(); + assert getType() == NodeType.KVNodeValue; + children[1] = value; + dirty = true; + return this; + } + + public Object kvNodeGetValueOrNode() { + parse(); + assert getType() != NodeType.BranchNode; + return children[1]; + } + + public Node kvNodeSetValueOrNode(Object valueOrNode) { + parse(); + assert getType() != NodeType.BranchNode; + children[1] = valueOrNode; + dirty = true; + return this; + } + + public NodeType getType() { + parse(); + + return children.length == 17 ? NodeType.BranchNode : + (children[1] instanceof Node ? NodeType.KVNodeNode : NodeType.KVNodeValue); + } + + public void dispose() { + if (hash != null) { + deleteHash(hash); + } + } + + public Node invalidate() { + dirty = true; + return this; + } + + /*********** Dump methods ************/ + + public String dumpStruct(String indent, String prefix) { + String ret = indent + prefix + getType() + (dirty ? " *" : "") + + (hash == null ? "" : "(hash: " + Hex.toHexString(hash).substring(0, 6) + ")"); + if (getType() == NodeType.BranchNode) { + byte[] value = branchNodeGetValue(); + ret += (value == null ? "" : " [T] = " + Hex.toHexString(value)) + "\n"; + for (int i = 0; i < 16; i++) { + Node child = branchNodeGetChild(i); + if (child != null) { + ret += child.dumpStruct(indent + " ", "[" + i + "] "); + } + } + + } else if (getType() == NodeType.KVNodeNode) { + ret += " [" + kvNodeGetKey() + "]\n"; + ret += kvNodeGetChildNode().dumpStruct(indent + " ", ""); + } else { + ret += " [" + kvNodeGetKey() + "] = " + Hex.toHexString(kvNodeGetValue()) + "\n"; + } + return ret; + } + + public List dumpTrieNode(boolean compact) { + List ret = new ArrayList<>(); + if (hash != null) { + ret.add(hash2str(hash, compact) + " ==> " + dumpContent(false, compact)); + } + + if (getType() == NodeType.BranchNode) { + for (int i = 0; i < 16; i++) { + Node child = branchNodeGetChild(i); + if (child != null) { + ret.addAll(child.dumpTrieNode(compact)); + } + } + } else if (getType() == NodeType.KVNodeNode) { + ret.addAll(kvNodeGetChildNode().dumpTrieNode(compact)); + } + return ret; + } + + private String dumpContent(boolean recursion, boolean compact) { + if (recursion && hash != null) { + return hash2str(hash, compact); + } + String ret; + if (getType() == NodeType.BranchNode) { + ret = "["; + for (int i = 0; i < 16; i++) { + Node child = branchNodeGetChild(i); + ret += i == 0 ? "" : ","; + ret += child == null ? "" : child.dumpContent(true, compact); + } + byte[] value = branchNodeGetValue(); + ret += value == null ? "" : ", " + val2str(value, compact); + ret += "]"; + } else if (getType() == NodeType.KVNodeNode) { + ret = "[<" + kvNodeGetKey() + ">, " + kvNodeGetChildNode().dumpContent(true, compact) + "]"; + } else { + ret = "[<" + kvNodeGetKey() + ">, " + val2str(kvNodeGetValue(), compact) + "]"; + } + return ret; + } + + public NodeType getNodeType() { + return nodeType; + } + + public Node setNodeType(NodeType nodeType) { + this.nodeType = nodeType; + return this; + } + + @Override + public String toString() { + return getType() + (dirty ? " *" : "") + (hash == null ? "" + : "(hash: " + toHexString(hash) + " )"); + } + } + + public interface ScanAction { + + void doOnNode(byte[] hash, Node node); + + void doOnValue(byte[] nodeHash, Node node, byte[] key, byte[] value); + } + + private DB cache; + private Node root; + private boolean async = true; + + public TrieImpl() { + this((byte[]) null); + } + + public TrieImpl(byte[] root) { + this(new ConcurrentHashDB(), root); + } + + public TrieImpl(DB cache) { + this(cache, null); + } + + public TrieImpl(DB cache, byte[] root) { + this.cache = cache; + setRoot(root); + } + + public void setAsync(boolean async) { + this.async = async; + } + + private void encode() { + if (root != null) { + root.encode(); + } + } + + public void setRoot(byte[] root) { + if (root != null && !FastByteComparisons.equalByte(root, EMPTY_TRIE_HASH)) { + this.root = new Node(root); + } else { + this.root = null; + } + + } + + private boolean hasRoot() { + return root != null && root.resolveCheck(); + } + + public DB getCache() { + return cache; + } + + private byte[] getHash(byte[] hash) { + BytesCapsule bytesCapsule = cache.get(hash); + return bytesCapsule == null ? null : bytesCapsule.getData(); + } + + private void addHash(byte[] hash, byte[] ret) { + cache.put(hash, new BytesCapsule(ret)); + } + + private void deleteHash(byte[] hash) { + cache.remove(hash); + } + + public byte[] get(byte[] key) { + if (!hasRoot()) { + return null; // treating unknown root hash as empty trie + } + TrieKey k = TrieKey.fromNormal(key); + return get(root, k); + } + + private byte[] get(Node n, TrieKey k) { + if (n == null) { + return null; + } + + NodeType type = n.getType(); + if (type == NodeType.BranchNode) { + if (k.isEmpty()) { + return n.branchNodeGetValue(); + } + Node childNode = n.branchNodeGetChild(k.getHex(0)); + return get(childNode, k.shift(1)); + } else { + TrieKey k1 = k.matchAndShift(n.kvNodeGetKey()); + if (k1 == null) { + return null; + } + if (type == NodeType.KVNodeValue) { + return k1.isEmpty() ? n.kvNodeGetValue() : null; + } else { + return get(n.kvNodeGetChildNode(), k1); + } + } + } + + public void put(byte[] key, byte[] value) { + TrieKey k = TrieKey.fromNormal(key); + if (root == null) { + if (value != null && value.length > 0) { + root = new Node(k, value); + } + } else { + if (value == null || value.length == 0) { + root = delete(root, k); + } else { + root = insert(root, k, value); + } + } + } + + private Node insert(Node n, TrieKey k, Object nodeOrValue) { + NodeType type = n.getType(); + if (type == NodeType.BranchNode) { + if (k.isEmpty()) { + return n.branchNodeSetValue((byte[]) nodeOrValue); + } + Node childNode = n.branchNodeGetChild(k.getHex(0)); + if (childNode != null) { + return n.branchNodeSetChild(k.getHex(0), insert(childNode, k.shift(1), nodeOrValue)); + } else { + TrieKey childKey = k.shift(1); + Node newChildNode; + if (!childKey.isEmpty()) { + newChildNode = new Node(childKey, nodeOrValue); + } else { + newChildNode = nodeOrValue instanceof Node ? + (Node) nodeOrValue : new Node(childKey, nodeOrValue); + } + return n.branchNodeSetChild(k.getHex(0), newChildNode); + } + } else { + TrieKey currentNodeKey = n.kvNodeGetKey(); + TrieKey commonPrefix = k.getCommonPrefix(currentNodeKey); + if (commonPrefix.isEmpty()) { + Node newBranchNode = new Node(); + insert(newBranchNode, currentNodeKey, n.kvNodeGetValueOrNode()); + insert(newBranchNode, k, nodeOrValue); + n.dispose(); + return newBranchNode; + } else if (commonPrefix.equals(k)) { + return n.kvNodeSetValueOrNode(nodeOrValue); + } else if (commonPrefix.equals(currentNodeKey)) { + insert(n.kvNodeGetChildNode(), k.shift(commonPrefix.getLength()), nodeOrValue); + return n.invalidate(); + } else { + Node newBranchNode = new Node(); + Node newKvNode = new Node(commonPrefix, newBranchNode); + // TODO can be optimized + insert(newKvNode, currentNodeKey, n.kvNodeGetValueOrNode()); + insert(newKvNode, k, nodeOrValue); + n.dispose(); + return newKvNode; + } + } + } + + @Override + public void delete(byte[] key) { + TrieKey k = TrieKey.fromNormal(key); + if (root != null) { + root = delete(root, k); + } + } + + private Node delete(Node n, TrieKey k) { + NodeType type = n.getType(); + Node newKvNode; + if (type == NodeType.BranchNode) { + if (k.isEmpty()) { + n.branchNodeSetValue(null); + } else { + int idx = k.getHex(0); + Node child = n.branchNodeGetChild(idx); + if (child == null) { + return n; // no key found + } + + Node newNode = delete(child, k.shift(1)); + n.branchNodeSetChild(idx, newNode); + if (newNode != null) { + return n; // newNode != null thus number of children didn't decrease + } + } + + // child node or value was deleted and the branch node may need to be compacted + int compactIdx = n.branchNodeCompactIdx(); + if (compactIdx < 0) { + return n; // no compaction is required + } + + // only value or a single child left - compact branch node to kvNode + n.dispose(); + if (compactIdx == 16) { // only value left + return new Node(TrieKey.empty(true), n.branchNodeGetValue()); + } else { // only single child left + newKvNode = new Node(TrieKey.singleHex(compactIdx), n.branchNodeGetChild(compactIdx)); + } + } else { // n - kvNode + TrieKey k1 = k.matchAndShift(n.kvNodeGetKey()); + if (k1 == null) { + // no key found + return n; + } else if (type == NodeType.KVNodeValue) { + if (k1.isEmpty()) { + // delete this kvNode + n.dispose(); + return null; + } else { + // else no key found + return n; + } + } else { + Node newChild = delete(n.kvNodeGetChildNode(), k1); + if (newChild == null) { + throw new RuntimeException("Shouldn't happen"); + } + newKvNode = n.kvNodeSetValueOrNode(newChild); + } + } + + // if we get here a new kvNode was created, now need to check + // if it should be compacted with child kvNode + Node newChild = newKvNode.kvNodeGetChildNode(); + if (newChild.getType() != NodeType.BranchNode) { + // two kvNodes should be compacted into a single one + TrieKey newKey = newKvNode.kvNodeGetKey().concat(newChild.kvNodeGetKey()); + Node newNode = new Node(newKey, newChild.kvNodeGetValueOrNode()); + newChild.dispose(); + newKvNode.dispose(); + return newNode; + } else { + // no compaction needed + return newKvNode; + } + } + + @Override + public byte[] getRootHash() { + encode(); + return root != null ? root.hash : EMPTY_TRIE_HASH; + } + + @Override + public void clear() { + throw new RuntimeException("Not implemented yet"); + } + + @Override + public boolean flush() { + if (root != null && root.dirty) { + // persist all dirty nodes to underlying Source + encode(); + // release all Trie Node instances for GC + root = new Node(root.hash); + return true; + } else { + return false; + } + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + TrieImpl trieImpl1 = (TrieImpl) o; + + return FastByteComparisons.equalByte(getRootHash(), trieImpl1.getRootHash()); + + } + + @Override + public int hashCode() { + return super.hashCode(); + } + + public String dumpStructure() { + return root == null ? "" : root.dumpStruct("", ""); + } + + public String dumpTrie() { + return dumpTrie(true); + } + + public String dumpTrie(boolean compact) { + if (root == null) { + return ""; + } + encode(); + StrBuilder ret = new StrBuilder(); + List strings = root.dumpTrieNode(compact); + ret.append("Root: " + hash2str(getRootHash(), compact) + "\n"); + for (String s : strings) { + ret.append(s).append('\n'); + } + return ret.toString(); + } + + public void scanTree(ScanAction scanAction) { + scanTree(root, TrieKey.empty(false), scanAction); + } + + public void scanTree(Node node, TrieKey k, ScanAction scanAction) { + if (node == null) { + return; + } + if (node.hash != null) { + scanAction.doOnNode(node.hash, node); + } + if (node.getType() == NodeType.BranchNode) { + if (node.branchNodeGetValue() != null) { + scanAction.doOnValue(node.hash, node, k.toNormal(), node.branchNodeGetValue()); + } + for (int i = 0; i < 16; i++) { + scanTree(node.branchNodeGetChild(i), k.concat(TrieKey.singleHex(i)), scanAction); + } + } else if (node.getType() == NodeType.KVNodeNode) { + scanTree(node.kvNodeGetChildNode(), k.concat(node.kvNodeGetKey()), scanAction); + } else { + scanAction.doOnValue(node.hash, node, k.concat(node.kvNodeGetKey()).toNormal(), + node.kvNodeGetValue()); + } + } + + public LinkedHashMap prove(byte[] key) { + Node node = root; + List nodeList = new ArrayList<>(); + if (node == null) { + return null; + } + TrieKey trieKey = TrieKey.fromNormal(key); + while (node != null) { + Node n = node; + if (n.getType() == NodeType.BranchNode) { + if (trieKey.isEmpty()) { + nodeList.add(n); + break; + } + node = (Node) n.branchNodeGetChild(trieKey.getHex(0)); + if (node == null) { + return null; + } + trieKey = trieKey.shift(1); + nodeList.add(n); + } else if (n.getType() == NodeType.KVNodeNode) { + TrieKey currentNodeKey = n.kvNodeGetKey(); + TrieKey commonPrefix = trieKey.getCommonPrefix(currentNodeKey); + if (commonPrefix.getLength() != currentNodeKey.getLength()) { + return null; + } + node = n.kvNodeGetChildNode(); + if (node == null) { + return null; + } + trieKey = trieKey.shift(commonPrefix.getLength()); + nodeList.add(n); + } else { + if (!n.kvNodeGetKey().equals(trieKey)) { + return null; + } + nodeList.add(n); + break; + } + } + LinkedHashMap nodeMap = new LinkedHashMap<>(); + int i = 0; + for (Node n : nodeList) { + List cpList = new ArrayList<>(); + nodeMap.put(childrenHash(n, cpList, 0, i == 0 ? true : false), cpList.get(0)); + ++i; + } + return nodeMap; + } + + private byte[] childrenHash(Node n, List cpList, int level, boolean forceHash) { + n.toString();//init children + Node cp = new Node(n.children.length); + if (level == 0) { + cpList.add(cp); + } + Object[] hashArray = new Object[n.children.length]; + if (n.getType() == NodeType.BranchNode) { + cp.setNodeType(NodeType.BranchNode); + for (int i = 0; i < 16; i++) { + Node cNode = n.branchNodeGetChild(i); + if (cNode != null) { + if (cNode.hash == null) { + byte[] childrenHash = childrenHash(cNode, cpList, level + 1, false); + cp.children[i] = + childrenHash.length < 32 && !forceHash ? childrenHash : encodeElement(childrenHash); + } else { + cp.children[i] = encodeElement(cNode.hash); + } + } else {//todo + cp.children[i] = EMPTY_ELEMENT_RLP; + } + } + byte[] value = n.branchNodeGetValue(); + cp.children[16] = value == null ? EMPTY_ELEMENT_RLP : encodeElement(value); + hashArray = cp.children.clone(); + } else if (n.getType() == NodeType.KVNodeNode) { + cp.setNodeType(NodeType.KVNodeNode); + TrieKey trieKey = n.kvNodeGetKey(); + Node cNode = n.kvNodeGetChildNode(); + cp.children[0] = encodeElement(trieKey.toPacked()); + if (cNode.hash == null) { + byte[] childrenHash = childrenHash(cNode, cpList, level + 1, false); + cp.children[1] = + childrenHash.length < 32 && !forceHash ? childrenHash : encodeElement(childrenHash); + } else { + cp.children[1] = encodeElement(cNode.hash); + } + hashArray = cp.children.clone(); + cp.children[0] = trieKey; + } else { + cp.setNodeType(NodeType.KVNodeValue); + byte[] value = n.kvNodeGetValue(); + TrieKey trieKey = n.kvNodeGetKey(); + cp.children[0] = encodeElement(trieKey.toPacked()); + cp.children[1] = encodeElement(value == null ? EMPTY_BYTE_ARRAY : value); + hashArray = cp.children.clone(); + cp.children[0] = trieKey; + } + byte[] ret = RLP.encodeList(hashArray); + if (ret.length < 32 && !forceHash) { + return ret; + } else { + return Hash.sha3(ret); + } + } + + public boolean verifyProof(byte[] rootHash, byte[] key, LinkedHashMap nodeMap) { + if (nodeMap == null || rootHash == null || rootHash.length <= 0 || key == null + || key.length <= 0) { + return false; + } + int i = 0; + TrieKey trieKey = TrieKey.fromNormal(key); + byte[] beforeNode = new byte[0]; + for (Entry entry : nodeMap.entrySet()) { + if (i > 0) { + byte[] hash = (beforeNode.length < 32) ? entry.getKey() : encodeElement(entry.getKey()); + if (!Arrays.equals(beforeNode, hash)) { + return false; + } + } + // + switch (entry.getValue().getNodeType()) { + case BranchNode: { + if (trieKey.isEmpty()) { + break; + } + beforeNode = (byte[]) entry.getValue().children[trieKey.getHex(0)]; + trieKey = trieKey.shift(1); + } + break; + case KVNodeNode: { + TrieKey currentNodeKey = (TrieKey) entry.getValue().children[0]; + entry.getValue().children[0] = encodeElement(currentNodeKey.toPacked()); + TrieKey commonPrefix = trieKey.getCommonPrefix(currentNodeKey); + if (commonPrefix.getLength() != currentNodeKey.getLength()) { + return false; + } + beforeNode = (byte[]) entry.getValue().children[1]; + trieKey = trieKey.shift(commonPrefix.getLength()); + } + break; + case KVNodeValue: { + TrieKey currentNodeKey = (TrieKey) entry.getValue().children[0]; + entry.getValue().children[0] = encodeElement(currentNodeKey.toPacked()); + if (!currentNodeKey.equals(trieKey)) { + return false; + } + trieKey = trieKey.shift(trieKey.getLength()); + } + break; + default: + return false; + } + + if (i == 0 && !Arrays.equals(rootHash, entry.getKey())) { + return false; + } + byte[] hash = Hash.sha3(RLP.encodeList(entry.getValue().children)); + if (i > 0) { + byte[] encode = RLP.encodeList(entry.getValue().children); + hash = (encode.length < 32) ? encode : Hash.sha3(encode); + } + if (!Arrays.equals(hash, entry.getKey())) { + return false; + } + ++i; + } + if (trieKey.getLength() != 0) { + return false; + } + return true; + } + + public Node getRoot() { + return root; + } + + private static String hash2str(byte[] hash, boolean shortHash) { + String ret = Hex.toHexString(hash); + return "0x" + (shortHash ? ret.substring(0, 8) : ret); + } + + private static String val2str(byte[] val, boolean shortHash) { + String ret = Hex.toHexString(val); + if (val.length > 16) { + ret = ret.substring(0, 10) + "... len " + val.length; + } + return "\"" + ret + "\""; + } +} diff --git a/src/main/java/org/tron/core/trie/TrieKey.java b/src/main/java/org/tron/core/trie/TrieKey.java new file mode 100644 index 00000000000..28d4e0da67d --- /dev/null +++ b/src/main/java/org/tron/core/trie/TrieKey.java @@ -0,0 +1,198 @@ + +package org.tron.core.trie; + +import static org.tron.common.utils.ByteUtil.EMPTY_BYTE_ARRAY; +import static org.tron.common.utils.ByteUtil.toHexString; + +/** + * Created by Anton Nashatyrev on 13.02.2017. + */ +public final class TrieKey { + + public static final int ODD_OFFSET_FLAG = 0x1; + public static final int TERMINATOR_FLAG = 0x2; + private final byte[] key; + private final int off; + private final boolean terminal; + + public static TrieKey fromNormal(byte[] key) { + return new TrieKey(key); + } + + public static TrieKey fromPacked(byte[] key) { + return new TrieKey(key, ((key[0] >> 4) & ODD_OFFSET_FLAG) != 0 ? 1 : 2, + ((key[0] >> 4) & TERMINATOR_FLAG) != 0); + } + + public static TrieKey empty(boolean terminal) { + return new TrieKey(EMPTY_BYTE_ARRAY, 0, terminal); + } + + public static TrieKey singleHex(int hex) { + TrieKey ret = new TrieKey(new byte[1], 1, false); + ret.setHex(0, hex); + return ret; + } + + public TrieKey(byte[] key, int off, boolean terminal) { + this.terminal = terminal; + this.off = off; + this.key = key; + } + + private TrieKey(byte[] key) { + this(key, 0, true); + } + + public byte[] toPacked() { + int flags = ((off & 1) != 0 ? ODD_OFFSET_FLAG : 0) | (terminal ? TERMINATOR_FLAG : 0); + byte[] ret = new byte[getLength() / 2 + 1]; + int toCopy = (flags & ODD_OFFSET_FLAG) != 0 ? ret.length : ret.length - 1; + System.arraycopy(key, key.length - toCopy, ret, ret.length - toCopy, toCopy); + ret[0] &= 0x0F; + ret[0] |= flags << 4; + return ret; + } + + public byte[] toNormal() { + if ((off & 1) != 0) { + throw new RuntimeException( + "Can't convert a key with odd number of hexes to normal: " + this); + } + int arrLen = key.length - off / 2; + byte[] ret = new byte[arrLen]; + System.arraycopy(key, key.length - arrLen, ret, 0, arrLen); + return ret; + } + + public boolean isTerminal() { + return terminal; + } + + public boolean isEmpty() { + return getLength() == 0; + } + + public TrieKey shift(int hexCnt) { + return new TrieKey(this.key, off + hexCnt, terminal); + } + + public TrieKey getCommonPrefix(TrieKey k) { + // TODO can be optimized + int prefixLen = 0; + int thisLength = getLength(); + int kLength = k.getLength(); + while (prefixLen < thisLength && prefixLen < kLength && getHex(prefixLen) == k + .getHex(prefixLen)) { + prefixLen++; + } + byte[] prefixKey = new byte[(prefixLen + 1) >> 1]; + TrieKey ret = new TrieKey(prefixKey, (prefixLen & 1) == 0 ? 0 : 1, + prefixLen == getLength() && prefixLen == k.getLength() && terminal && k.isTerminal()); + for (int i = 0; i < prefixLen; i++) { + ret.setHex(i, k.getHex(i)); + } + return ret; + } + + public TrieKey matchAndShift(TrieKey k) { + int len = getLength(); + int kLen = k.getLength(); + if (len < kLen) { + return null; + } + + if ((off & 1) == (k.off & 1)) { + // optimization to compare whole keys bytes + if ((off & 1) == 1 && getHex(0) != k.getHex(0)) { + return null; + } + int idx1 = (off + 1) >> 1; + int idx2 = (k.off + 1) >> 1; + int l = kLen >> 1; + for (int i = 0; i < l; i++, idx1++, idx2++) { + if (key[idx1] != k.key[idx2]) { + return null; + } + } + } else { + for (int i = 0; i < kLen; i++) { + if (getHex(i) != k.getHex(i)) { + return null; + } + } + } + return shift(kLen); + } + + public int getLength() { + return (key.length << 1) - off; + } + + private void setHex(int idx, int hex) { + int byteIdx = (off + idx) >> 1; + if (((off + idx) & 1) == 0) { + key[byteIdx] &= 0x0F; + key[byteIdx] |= hex << 4; + } else { + key[byteIdx] &= 0xF0; + key[byteIdx] |= hex; + } + } + + public int getHex(int idx) { + byte b = key[(off + idx) >> 1]; + return (((off + idx) & 1) == 0 ? (b >> 4) : b) & 0xF; + } + + public TrieKey concat(TrieKey k) { + if (isTerminal()) { + throw new RuntimeException("Can' append to terminal key: " + this + " + " + k); + } + int len = getLength(); + int kLen = k.getLength(); + int newLen = len + kLen; + byte[] newKeyBytes = new byte[(newLen + 1) >> 1]; + TrieKey ret = new TrieKey(newKeyBytes, newLen & 1, k.isTerminal()); + for (int i = 0; i < len; i++) { + ret.setHex(i, getHex(i)); + } + for (int i = 0; i < kLen; i++) { + ret.setHex(len + i, k.getHex(i)); + } + return ret; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (this.getClass() != obj.getClass()) { + return false; + } + TrieKey k = (TrieKey) obj; + int len = getLength(); + + if (len != k.getLength()) { + return false; + } + // TODO can be optimized + for (int i = 0; i < len; i++) { + if (getHex(i) != k.getHex(i)) { + return false; + } + } + return isTerminal() == k.isTerminal(); + } + + @Override + public int hashCode() { + return super.hashCode(); + } + + @Override + public String toString() { + return toHexString(key).substring(off) + (isTerminal() ? "T" : ""); + } +} diff --git a/src/main/java/org/tron/core/witness/ProposalController.java b/src/main/java/org/tron/core/witness/ProposalController.java index fa208251855..78e2832eb49 100644 --- a/src/main/java/org/tron/core/witness/ProposalController.java +++ b/src/main/java/org/tron/core/witness/ProposalController.java @@ -1,11 +1,14 @@ package org.tron.core.witness; import com.google.protobuf.ByteString; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; +import org.tron.common.utils.ByteArray; import org.tron.core.capsule.ProposalCapsule; import org.tron.core.db.Manager; import org.tron.protos.Protocol.Proposal.State; @@ -202,11 +205,23 @@ public void setDynamicParameters(ProposalCapsule proposalCapsule) { manager.getDynamicPropertiesStore().saveMultiSignFee(entry.getValue()); break; } + case (24): { + manager.getDynamicPropertiesStore().saveAllowProtoFilterNum(entry.getValue()); + break; + } + case (25): { + manager.getDynamicPropertiesStore().saveAllowAccountStateRoot(entry.getValue()); + break; + } + case (26): { + manager.getDynamicPropertiesStore().saveAllowTvmConstantinople(entry.getValue()); + manager.getDynamicPropertiesStore().addSystemContractAndSetPermission(48); + break; + } default: break; } } } - } diff --git a/src/main/java/org/tron/program/Version.java b/src/main/java/org/tron/program/Version.java index 1a937104904..c81b80b95bf 100644 --- a/src/main/java/org/tron/program/Version.java +++ b/src/main/java/org/tron/program/Version.java @@ -1,7 +1,7 @@ package org.tron.program; public class Version { - private static final String version = "3.5.1"; + private static final String version = "3.6.0"; public static final String versionName = "Odyssey-v3.5.0.1-318-gc6864f595"; public static final String versionCode = "9911"; diff --git a/src/main/protos/api/api.proto b/src/main/protos/api/api.proto index 6066d62c476..50e7f0950ec 100644 --- a/src/main/protos/api/api.proto +++ b/src/main/protos/api/api.proto @@ -404,6 +404,12 @@ service Wallet { rpc TriggerContract (TriggerSmartContract) returns (TransactionExtention) { } + rpc TriggerConstantContract (TriggerSmartContract) returns (TransactionExtention) { + } + + rpc ClearContractABI (ClearABIContract) returns (TransactionExtention) { + } + rpc ListWitnesses (EmptyMessage) returns (WitnessList) { option (google.api.http) = { post: "/wallet/listwitnesses" @@ -734,6 +740,7 @@ service WalletSolidity { } }; } + rpc GetTransactionInfoById (BytesMessage) returns (TransactionInfo) { option (google.api.http) = { post: "/walletsolidity/gettransactioninfobyid" @@ -743,6 +750,7 @@ service WalletSolidity { } }; } + //Warning: do not invoke this interface provided by others. rpc GenerateAddress (EmptyMessage) returns (AddressPrKeyPairMessage) { option (google.api.http) = { diff --git a/src/main/protos/core/Contract.proto b/src/main/protos/core/Contract.proto index 665632afda4..e9a66239091 100644 --- a/src/main/protos/core/Contract.proto +++ b/src/main/protos/core/Contract.proto @@ -84,6 +84,11 @@ message UpdateEnergyLimitContract { int64 origin_energy_limit = 3; } +message ClearABIContract { + bytes owner_address = 1; + bytes contract_address = 2; +} + message WitnessCreateContract { bytes owner_address = 1; bytes url = 2; diff --git a/src/main/protos/core/Tron.proto b/src/main/protos/core/Tron.proto index 374305bb6c9..5f6f4167aa5 100644 --- a/src/main/protos/core/Tron.proto +++ b/src/main/protos/core/Tron.proto @@ -272,6 +272,7 @@ message Transaction { ExchangeTransactionContract = 44; UpdateEnergyLimitContract = 45; AccountPermissionUpdateContract = 46; + ClearABIContract = 48; } ContractType type = 1; google.protobuf.Any parameter = 2; @@ -300,6 +301,7 @@ message Transaction { OUT_OF_TIME = 11; JVM_STACK_OVER_FLOW = 12; UNKNOWN = 13; + TRANSFER_FAILED = 14; } int64 fee = 1; code ret = 2; @@ -387,6 +389,7 @@ message BlockHeader { int64 witness_id = 8; bytes witness_address = 9; int32 version = 10; + bytes accountStateRoot = 11; } raw raw_data = 1; bytes witness_signature = 2; @@ -539,7 +542,8 @@ message SmartContract { int64 consume_user_resource_percent = 6; string name = 7; int64 origin_energy_limit = 8; - + bytes code_hash = 9; + bytes trx_hash = 10; } message InternalTransaction { diff --git a/src/main/resources/config-localtest.conf b/src/main/resources/config-localtest.conf index d28c70493a2..a9e7a47724d 100644 --- a/src/main/resources/config-localtest.conf +++ b/src/main/resources/config-localtest.conf @@ -265,7 +265,7 @@ block = { vm = { - supportConstant = false + supportConstant = true minTimeRatio = 0.0 maxTimeRatio = 5.0 } diff --git a/src/main/resources/config.conf b/src/main/resources/config.conf index 4f120313796..ba3cfffe83b 100644 --- a/src/main/resources/config.conf +++ b/src/main/resources/config.conf @@ -11,7 +11,6 @@ storage { db.directory = "database", index.directory = "index", transHistory.switch = "on", - # You can custom these 14 databases' configs: # account, account-index, asset-issue, block, block-index, @@ -121,6 +120,8 @@ node { maxActiveNodesWithSameIp = 2 + maxHttpConnectNumber = 50 + minParticipationRate = 15 # check the peer data transfer ,disconnect factor @@ -449,9 +450,16 @@ committee = { } event.subscribe = { + native = { + useNativeQueue = true // if true, use native message queue, else use event plugin. + bindport = 5555 // bind port + sendqueuelength = 1000 //max length of send queue + } + path = "" // absolute path of plugin server = "" // target server address to receive event triggers dbconfig="" // dbname|username|password + contractParse = true, topics = [ { triggerName = "block" // block trigger, the value can't be modified @@ -465,12 +473,12 @@ event.subscribe = { }, { triggerName = "contractevent" - enable = true + enable = false topic = "contractevent" }, { triggerName = "contractlog" - enable = true + enable = false topic = "contractlog" } ] diff --git a/src/test/java/org/tron/common/logsfilter/EventLoaderTest.java b/src/test/java/org/tron/common/logsfilter/EventLoaderTest.java new file mode 100644 index 00000000000..6413adc8824 --- /dev/null +++ b/src/test/java/org/tron/common/logsfilter/EventLoaderTest.java @@ -0,0 +1,31 @@ +package org.tron.common.logsfilter; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +public class EventLoaderTest { + @Test + public void launchNativeQueue(){ + EventPluginConfig config = new EventPluginConfig(); + config.setSendQueueLength(1000); + config.setBindPort(5555); + config.setUseNativeQueue(true); + + List triggerConfigList = new ArrayList<>(); + + TriggerConfig blockTriggerConfig = new TriggerConfig(); + blockTriggerConfig.setTriggerName("block"); + blockTriggerConfig.setEnabled(true); + blockTriggerConfig.setTopic("block"); + triggerConfigList.add(blockTriggerConfig); + + config.setTriggerConfigList(triggerConfigList); + + Assert.assertEquals(true,EventPluginLoader.getInstance().start(config)); + + EventPluginLoader.getInstance().stopPlugin(); + } +} diff --git a/src/test/java/org/tron/common/logsfilter/EventParserJsonTest.java b/src/test/java/org/tron/common/logsfilter/EventParserJsonTest.java new file mode 100644 index 00000000000..b43ef395608 --- /dev/null +++ b/src/test/java/org/tron/common/logsfilter/EventParserJsonTest.java @@ -0,0 +1,70 @@ +package org.tron.common.logsfilter; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import org.junit.Test; +import org.testng.Assert; +import org.tron.common.crypto.Hash; +import org.tron.common.utils.ByteArray; +import org.tron.core.Constant; +import org.tron.core.Wallet; + +public class EventParserJsonTest { + + @Test + public synchronized void testEventParser() { + + Wallet.setAddressPreFixByte(Constant.ADD_PRE_FIX_BYTE_MAINNET); + + String eventSign = "eventBytesL(address,bytes,bytes32,uint256,string)"; + + String abiStr = "[{\"constant\":false,\"inputs\":[{\"name\":\"_address\",\"type\":\"address\"},{\"name\":\"_random\",\"type\":\"bytes\"}],\"name\":\"randomNum\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":true,\"inputs\":[{\"indexed\":true,\"name\":\"addr\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"random\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"last1\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"t2\",\"type\":\"uint256\"}],\"name\":\"eventAnonymous\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"addr\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"random\",\"type\":\"bytes\"},{\"indexed\":true,\"name\":\"last1\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"t2\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"str\",\"type\":\"string\"}],\"name\":\"eventBytesL\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"addr\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"random\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"last1\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"t2\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"str\",\"type\":\"string\"}],\"name\":\"eventBytes\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"addr\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"random\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"last1\",\"type\":\"bytes32[]\"},{\"indexed\":false,\"name\":\"t2\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"str\",\"type\":\"string\"}],\"name\":\"eventByteArr\",\"type\":\"event\"}]"; + + String dataStr = "0x000000000000000000000000ca35b7d915458ef540ade6068dfe2f44e8fa733c0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000020109000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a6162636465666731323300000000000000000000000000000000000000000000"; + + byte[] data = ByteArray.fromHexString(dataStr); + List topicList = new LinkedList<>(); + topicList.add(Hash.sha3(eventSign.getBytes())); + topicList.add(ByteArray + .fromHexString("0xb7685f178b1c93df3422f7bfcb61ae2c6f66d0947bb9eb293259c231b986b81b")); + + JSONArray entryArr = JSONObject.parseArray(abiStr); + JSONObject entry = new JSONObject(); + + for (int i = 0; i < entryArr.size(); i++) { + JSONObject e = entryArr.getJSONObject(i); + System.out.println(e.getString("name")); + if (e.getString("name") != null) { + if (e.getString("name").equalsIgnoreCase("eventBytesL")) { + entry = e; + break; + } + } + } + + Assert.assertNotNull(entry); + Map dataMap = ContractEventParserJson.parseEventData(data, topicList, entry); + Map topicMap = ContractEventParserJson.parseTopics(topicList, entry); + + Assert.assertEquals(dataMap.get("0"), "TUQPrDEJkV4ttkrL7cVv1p3mikWYfM7LWt"); + Assert.assertEquals(dataMap.get("addr"), "TUQPrDEJkV4ttkrL7cVv1p3mikWYfM7LWt"); + + Assert.assertEquals(dataMap.get("1"), "0109"); + Assert.assertEquals(dataMap.get("random"), "0109"); + + Assert.assertEquals(topicMap.get("2"), + "b7685f178b1c93df3422f7bfcb61ae2c6f66d0947bb9eb293259c231b986b81b"); + Assert.assertEquals(topicMap.get("last1"), + "b7685f178b1c93df3422f7bfcb61ae2c6f66d0947bb9eb293259c231b986b81b"); + + Assert.assertEquals(dataMap.get("3"), "1"); + Assert.assertEquals(dataMap.get("t2"), "1"); + + Assert.assertEquals(dataMap.get("4"), "abcdefg123"); + Assert.assertEquals(dataMap.get("str"), "abcdefg123"); + + } +} diff --git a/src/test/java/org/tron/common/logsfilter/EventParserTest.java b/src/test/java/org/tron/common/logsfilter/EventParserTest.java index 7bae652c74a..fc6ebcf5572 100644 --- a/src/test/java/org/tron/common/logsfilter/EventParserTest.java +++ b/src/test/java/org/tron/common/logsfilter/EventParserTest.java @@ -1,25 +1,17 @@ package org.tron.common.logsfilter; -import org.apache.commons.lang3.ArrayUtils; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; import org.junit.Test; -import org.spongycastle.util.encoders.Hex; import org.testng.Assert; import org.tron.common.crypto.Hash; -import org.tron.common.runtime.TVMTestResult; -import org.tron.common.runtime.TVMTestUtils; +import org.tron.common.runtime.TvmTestUtils; import org.tron.common.runtime.vm.LogInfoTriggerParser; import org.tron.common.utils.ByteArray; import org.tron.core.Constant; import org.tron.core.Wallet; -import org.tron.core.services.http.JsonFormat; -import org.tron.protos.Protocol; -import org.tron.protos.Protocol.SmartContract; import org.tron.protos.Protocol.SmartContract.ABI; -import org.tron.protos.Protocol.SmartContract.ABI.Builder; - -import java.util.LinkedList; -import java.util.List; -import java.util.Map; public class EventParserTest { @@ -33,7 +25,7 @@ public synchronized void testEventParser() { String abiStr = "[{\"constant\":false,\"inputs\":[{\"name\":\"_address\",\"type\":\"address\"},{\"name\":\"_random\",\"type\":\"bytes\"}],\"name\":\"randomNum\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":true,\"inputs\":[{\"indexed\":true,\"name\":\"addr\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"random\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"last1\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"t2\",\"type\":\"uint256\"}],\"name\":\"eventAnonymous\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"addr\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"random\",\"type\":\"bytes\"},{\"indexed\":true,\"name\":\"last1\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"t2\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"str\",\"type\":\"string\"}],\"name\":\"eventBytesL\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"addr\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"random\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"last1\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"t2\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"str\",\"type\":\"string\"}],\"name\":\"eventBytes\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"addr\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"random\",\"type\":\"bytes\"},{\"indexed\":false,\"name\":\"\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"last1\",\"type\":\"bytes32[]\"},{\"indexed\":false,\"name\":\"t2\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"str\",\"type\":\"string\"}],\"name\":\"eventByteArr\",\"type\":\"event\"}]"; String dataStr = "0x000000000000000000000000ca35b7d915458ef540ade6068dfe2f44e8fa733c0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000020109000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a6162636465666731323300000000000000000000000000000000000000000000"; - ABI abi = TVMTestUtils.jsonStr2ABI(abiStr); + ABI abi = TvmTestUtils.jsonStr2Abi(abiStr); byte[] data = ByteArray.fromHexString(dataStr); List topicList = new LinkedList<>(); @@ -54,8 +46,8 @@ public synchronized void testEventParser() { Assert.assertEquals(Hash.sha3(LogInfoTriggerParser.getEntrySignature(entry).getBytes()), topicList.get(0)); Assert.assertNotNull(entry); - Map dataMap = ContractEventParser.parseEventData(data, topicList, entry); - Map topicMap = ContractEventParser.parseTopics(topicList, entry); + Map dataMap = ContractEventParserAbi.parseEventData(data, topicList, entry); + Map topicMap = ContractEventParserAbi.parseTopics(topicList, entry); Assert.assertEquals(dataMap.get("0"), "TUQPrDEJkV4ttkrL7cVv1p3mikWYfM7LWt"); Assert.assertEquals(dataMap.get("addr"), "TUQPrDEJkV4ttkrL7cVv1p3mikWYfM7LWt"); diff --git a/src/test/java/org/tron/common/logsfilter/NativeMessageQueueTest.java b/src/test/java/org/tron/common/logsfilter/NativeMessageQueueTest.java new file mode 100644 index 00000000000..13ddb94964d --- /dev/null +++ b/src/test/java/org/tron/common/logsfilter/NativeMessageQueueTest.java @@ -0,0 +1,74 @@ +package org.tron.common.logsfilter; + +import org.junit.Assert; +import org.junit.Test; +import org.tron.common.logsfilter.nativequeue.NativeMessageQueue; +import org.zeromq.SocketType; +import org.zeromq.ZContext; +import org.zeromq.ZMQ; + +public class NativeMessageQueueTest { + public int bindPort = 5555; + public String dataToSend = "################"; + public String topic = "testTopic"; + + @Test + public void invalidBindPort(){ + boolean bRet = NativeMessageQueue.getInstance().start(-1111, 0); + Assert.assertEquals(true, bRet); + NativeMessageQueue.getInstance().stop(); + } + + @Test + public void invalidSendLength(){ + boolean bRet = NativeMessageQueue.getInstance().start(0, -2222); + Assert.assertEquals(true, bRet); + NativeMessageQueue.getInstance().stop(); + } + + @Test + public void publishTrigger(){ + + int sendLength = 0; + boolean bRet = NativeMessageQueue.getInstance().start(bindPort, sendLength); + Assert.assertEquals(true, bRet); + + startSubscribeThread(); + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + NativeMessageQueue.getInstance().publishTrigger(dataToSend, topic); + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + NativeMessageQueue.getInstance().stop(); + } + + public void startSubscribeThread(){ + Thread thread = + new Thread(() -> { + ZContext context = new ZContext(); + ZMQ.Socket subscriber = context.createSocket(SocketType.SUB); + + Assert.assertEquals(true, subscriber.connect(String.format("tcp://localhost:%d", bindPort))); + Assert.assertEquals(true, subscriber.subscribe(topic)); + + while (!Thread.currentThread().isInterrupted()) { + byte[] message = subscriber.recv(); + String triggerMsg = new String(message); + + Assert.assertEquals(true, triggerMsg.contains(dataToSend) || triggerMsg.contains(topic)); + + } + }); + thread.start(); + } +} diff --git a/src/test/java/org/tron/common/runtime/InheritanceTest.java b/src/test/java/org/tron/common/runtime/InheritanceTest.java index 9c94c6758b6..60ecfc72f6f 100644 --- a/src/test/java/org/tron/common/runtime/InheritanceTest.java +++ b/src/test/java/org/tron/common/runtime/InheritanceTest.java @@ -88,14 +88,14 @@ public void inheritanceTest() long fee = 100000000; long consumeUserResourcePercent = 0; - byte[] contractAddress = TVMTestUtils.deployContractWholeProcessReturnContractAddress( + byte[] contractAddress = TvmTestUtils.deployContractWholeProcessReturnContractAddress( contractName, callerAddress, ABI, code, value, fee, consumeUserResourcePercent, null, deposit, null); /* =================================== CALL getName() return child value =================================== */ - byte[] triggerData1 = TVMTestUtils.parseABI("getName()", ""); - runtime = TVMTestUtils + byte[] triggerData1 = TvmTestUtils.parseAbi("getName()", ""); + runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(callerAddress, contractAddress, triggerData1, 0, 1000000, deposit, null); @@ -107,8 +107,8 @@ public void inheritanceTest() + "6261720000000000000000000000000000000000000000000000000000000000"); /* =================================== CALL getNumber() return parent value=================================== */ - byte[] triggerData2 = TVMTestUtils.parseABI("getNumber()", ""); - runtime = TVMTestUtils + byte[] triggerData2 = TvmTestUtils.parseAbi("getNumber()", ""); + runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(callerAddress, contractAddress, triggerData2, 0, 1000000, deposit, null); @@ -118,8 +118,8 @@ public void inheritanceTest() "0000000000000000000000000000000000000000000000000000000000000064"); /* =================================== CALL getId() call child function return parent field value=================================== */ - byte[] triggerData3 = TVMTestUtils.parseABI("getId()", ""); - runtime = TVMTestUtils + byte[] triggerData3 = TvmTestUtils.parseAbi("getId()", ""); + runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(callerAddress, contractAddress, triggerData3, 0, 1000000, deposit, null); diff --git a/src/test/java/org/tron/common/runtime/InternalTransactionComplexTest.java b/src/test/java/org/tron/common/runtime/InternalTransactionComplexTest.java index 6fd51f0957e..b97b1696781 100644 --- a/src/test/java/org/tron/common/runtime/InternalTransactionComplexTest.java +++ b/src/test/java/org/tron/common/runtime/InternalTransactionComplexTest.java @@ -81,15 +81,15 @@ public void internalTransactionAsInstanceTest() byte[] callerContractAddress = deployCallerContractAndGetItsAddress(calledContractAddress); /* =================================== CALL makeTheCall =================================== */ - byte[] triggerData1 = TVMTestUtils.parseABI("makeTheCall()", ""); - runtime = TVMTestUtils + byte[] triggerData1 = TvmTestUtils.parseAbi("makeTheCall()", ""); + runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), callerContractAddress, triggerData1, 0, 100000000, deposit, null); /* =================================== CALL testCallbackReturns_ to check data =================================== */ - byte[] triggerData2 = TVMTestUtils.parseABI("testCallbackReturns_()", ""); - runtime = TVMTestUtils + byte[] triggerData2 = TvmTestUtils.parseAbi("testCallbackReturns_()", ""); + runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), callerContractAddress, triggerData2, 0, 100000000, deposit, null); @@ -125,7 +125,7 @@ private byte[] deployCalledContractandGetItsAddress() long feeLimit = 1000000000; long consumeUserResourcePercent = 0; - return TVMTestUtils + return TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, null, deposit, null); @@ -159,7 +159,7 @@ private byte[] deployCallerContractAndGetItsAddress(byte[] calledContractAddress long feeLimit = 1000000000; long consumeUserResourcePercent = 0; - return TVMTestUtils + return TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, null, deposit, null); diff --git a/src/test/java/org/tron/common/runtime/ProgramResultTest.java b/src/test/java/org/tron/common/runtime/ProgramResultTest.java index a8432ebab36..0989559db31 100644 --- a/src/test/java/org/tron/common/runtime/ProgramResultTest.java +++ b/src/test/java/org/tron/common/runtime/ProgramResultTest.java @@ -16,8 +16,6 @@ import org.tron.common.runtime.vm.DataWord; import org.tron.common.runtime.vm.program.InternalTransaction; import org.tron.common.storage.DepositImpl; -import org.tron.common.utils.ByteArray; -import org.tron.common.utils.ByteString; import org.tron.common.utils.FileUtil; import org.tron.core.Constant; import org.tron.core.Wallet; @@ -35,7 +33,6 @@ import org.tron.protos.Protocol; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Transaction; -import org.tron.protos.Protocol.TransactionInfo; @Slf4j @@ -97,8 +94,8 @@ public void uniqueInternalTransactionHashTest() byte[] calledContractAddress = deployCalledContractAndGetItsAddress(); byte[] contractAAddress = deployContractAAndGetItsAddress(calledContractAddress); /* =================================== CALL create() =================================== */ - byte[] triggerData1 = TVMTestUtils.parseABI("create()", ""); - runtime = TVMTestUtils + byte[] triggerData1 = TvmTestUtils.parseAbi("create()", ""); + runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), contractAAddress, triggerData1, 0, 100000000, deposit, null); @@ -133,7 +130,7 @@ private byte[] deployCalledContractAndGetItsAddress() long feeLimit = 1000000000; long consumeUserResourcePercent = 0; - return TVMTestUtils + return TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, null, deposit, null); @@ -208,7 +205,7 @@ private byte[] deployContractAAndGetItsAddress(byte[] calledContractAddress) long feeLimit = 1000000000; long consumeUserResourcePercent = 0; - return TVMTestUtils + return TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, null, deposit, null); @@ -239,12 +236,12 @@ public void successAndFailResultTest() "0000000000000000000000000000000000000000000000000000000000000000"; // ======================================= Test Success ======================================= - byte[] triggerData1 = TVMTestUtils.parseABI("transfer(address,bool)", + byte[] triggerData1 = TvmTestUtils.parseAbi("transfer(address,bool)", params); - Transaction trx1 = TVMTestUtils + Transaction trx1 = TvmTestUtils .generateTriggerSmartContractAndGetTransaction(Hex.decode(OWNER_ADDRESS), aContract, triggerData1, 0, 100000000); - TransactionTrace traceSuccess = TVMTestUtils + TransactionTrace traceSuccess = TvmTestUtils .processTransactionAndReturnTrace(trx1, deposit, null); runtime = traceSuccess.getRuntime(); byte[] bContract = runtime.getResult().getHReturn(); @@ -283,12 +280,12 @@ public void successAndFailResultTest() // set revert == true params = Hex.toHexString(new DataWord(new DataWord(cContract).getLast20Bytes()).getData()) + "0000000000000000000000000000000000000000000000000000000000000001"; - byte[] triggerData2 = TVMTestUtils.parseABI("transfer(address,bool)", + byte[] triggerData2 = TvmTestUtils.parseAbi("transfer(address,bool)", params); - Transaction trx2 = TVMTestUtils + Transaction trx2 = TvmTestUtils .generateTriggerSmartContractAndGetTransaction(Hex.decode(OWNER_ADDRESS), aContract, triggerData2, 0, 100000000); - TransactionTrace traceFailed = TVMTestUtils + TransactionTrace traceFailed = TvmTestUtils .processTransactionAndReturnTrace(trx2, deposit, null); runtime = traceFailed.getRuntime(); byte[] bContract2 = Wallet @@ -339,7 +336,7 @@ private byte[] deployC() long feeLimit = 1000000000; long consumeUserResourcePercent = 0; - return TVMTestUtils + return TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, null, deposit, null); @@ -380,7 +377,7 @@ private byte[] deployA() long feeLimit = 1000000000; long consumeUserResourcePercent = 0; - return TVMTestUtils + return TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, null, deposit, null); @@ -402,12 +399,12 @@ public void suicideResultTest() .toHexString(new DataWord(new DataWord(TRANSFER_TO).getLast20Bytes()).getData()); // ======================================= Test Suicide ======================================= - byte[] triggerData1 = TVMTestUtils.parseABI("suicide(address)", + byte[] triggerData1 = TvmTestUtils.parseAbi("suicide(address)", params); - Transaction trx = TVMTestUtils + Transaction trx = TvmTestUtils .generateTriggerSmartContractAndGetTransaction(Hex.decode(OWNER_ADDRESS), suicideContract, triggerData1, 0, 100000000); - TransactionTrace trace = TVMTestUtils.processTransactionAndReturnTrace(trx, deposit, null); + TransactionTrace trace = TvmTestUtils.processTransactionAndReturnTrace(trx, deposit, null); runtime = trace.getRuntime(); List internalTransactionsList = runtime.getResult() .getInternalTransactions(); @@ -442,7 +439,7 @@ private byte[] deploySuicide() long feeLimit = 1000000000; long consumeUserResourcePercent = 0; - return TVMTestUtils + return TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, null, deposit, null); diff --git a/src/test/java/org/tron/common/runtime/RuntimeImplTest.java b/src/test/java/org/tron/common/runtime/RuntimeImplTest.java index d7659cb818c..bb5b75e47a6 100644 --- a/src/test/java/org/tron/common/runtime/RuntimeImplTest.java +++ b/src/test/java/org/tron/common/runtime/RuntimeImplTest.java @@ -1,7 +1,7 @@ package org.tron.common.runtime; -import static org.tron.common.runtime.TVMTestUtils.generateDeploySmartContractAndGetTransaction; -import static org.tron.common.runtime.TVMTestUtils.generateTriggerSmartContractAndGetTransaction; +import static org.tron.common.runtime.TvmTestUtils.generateDeploySmartContractAndGetTransaction; +import static org.tron.common.runtime.TvmTestUtils.generateTriggerSmartContractAndGetTransaction; import java.io.File; import lombok.extern.slf4j.Slf4j; @@ -173,14 +173,14 @@ public void getCallerAndCreatorEnergyLimit2With0PercentTest() String ABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"count\",\"type\":\"uint256\"}],\"name\":\"testConstant\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"count\",\"type\":\"uint256\"}],\"name\":\"testNotConstant\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"; String code = "608060405234801561001057600080fd5b50610112806100206000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806321964a3914604e5780634c6bb6eb146078575b600080fd5b348015605957600080fd5b5060766004803603810190808035906020019092919050505060a2565b005b348015608357600080fd5b5060a06004803603810190808035906020019092919050505060c4565b005b600080600091505b8282101560bf576001905060018201915060aa565b505050565b600080600091505b8282101560e1576001905060018201915060cc565b5050505600a165627a7a72305820267cf0ebf31051a92ff62bed7490045b8063be9f1e1a22d07dce257654c8c17b0029"; String libraryAddressPair = null; - TVMTestResult result = TVMTestUtils - .deployContractWithCreatorEnergyLimitAndReturnTVMTestResult(contractName, creatorAddress, + TVMTestResult result = TvmTestUtils + .deployContractWithCreatorEnergyLimitAndReturnTvmTestResult(contractName, creatorAddress, ABI, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair, dbManager, null, creatorEnergyLimit); byte[] contractAddress = result.getContractAddress(); - byte[] triggerData = TVMTestUtils.parseABI("testNotConstant()", null); + byte[] triggerData = TvmTestUtils.parseAbi("testNotConstant()", null); Transaction trx = generateTriggerSmartContractAndGetTransaction(callerAddress, contractAddress, triggerData, value, feeLimit); @@ -263,14 +263,14 @@ public void getCallerAndCreatorEnergyLimit2With40PercentTest() String ABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"count\",\"type\":\"uint256\"}],\"name\":\"testConstant\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"count\",\"type\":\"uint256\"}],\"name\":\"testNotConstant\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"; String code = "608060405234801561001057600080fd5b50610112806100206000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806321964a3914604e5780634c6bb6eb146078575b600080fd5b348015605957600080fd5b5060766004803603810190808035906020019092919050505060a2565b005b348015608357600080fd5b5060a06004803603810190808035906020019092919050505060c4565b005b600080600091505b8282101560bf576001905060018201915060aa565b505050565b600080600091505b8282101560e1576001905060018201915060cc565b5050505600a165627a7a72305820267cf0ebf31051a92ff62bed7490045b8063be9f1e1a22d07dce257654c8c17b0029"; String libraryAddressPair = null; - TVMTestResult result = TVMTestUtils - .deployContractWithCreatorEnergyLimitAndReturnTVMTestResult(contractName, creatorAddress, + TVMTestResult result = TvmTestUtils + .deployContractWithCreatorEnergyLimitAndReturnTvmTestResult(contractName, creatorAddress, ABI, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair, dbManager, null, creatorEnergyLimit); byte[] contractAddress = result.getContractAddress(); - byte[] triggerData = TVMTestUtils.parseABI("testNotConstant()", null); + byte[] triggerData = TvmTestUtils.parseAbi("testNotConstant()", null); Transaction trx = generateTriggerSmartContractAndGetTransaction(callerAddress, contractAddress, triggerData, value, feeLimit); @@ -329,14 +329,14 @@ public void getCallerAndCreatorEnergyLimit2With100PercentTest() String ABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"count\",\"type\":\"uint256\"}],\"name\":\"testConstant\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"count\",\"type\":\"uint256\"}],\"name\":\"testNotConstant\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"; String code = "608060405234801561001057600080fd5b50610112806100206000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806321964a3914604e5780634c6bb6eb146078575b600080fd5b348015605957600080fd5b5060766004803603810190808035906020019092919050505060a2565b005b348015608357600080fd5b5060a06004803603810190808035906020019092919050505060c4565b005b600080600091505b8282101560bf576001905060018201915060aa565b505050565b600080600091505b8282101560e1576001905060018201915060cc565b5050505600a165627a7a72305820267cf0ebf31051a92ff62bed7490045b8063be9f1e1a22d07dce257654c8c17b0029"; String libraryAddressPair = null; - TVMTestResult result = TVMTestUtils - .deployContractWithCreatorEnergyLimitAndReturnTVMTestResult(contractName, creatorAddress, + TVMTestResult result = TvmTestUtils + .deployContractWithCreatorEnergyLimitAndReturnTvmTestResult(contractName, creatorAddress, ABI, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair, dbManager, null, creatorEnergyLimit); byte[] contractAddress = result.getContractAddress(); - byte[] triggerData = TVMTestUtils.parseABI("testNotConstant()", null); + byte[] triggerData = TvmTestUtils.parseAbi("testNotConstant()", null); Transaction trx = generateTriggerSmartContractAndGetTransaction(callerAddress, contractAddress, triggerData, value, feeLimit); diff --git a/src/test/java/org/tron/common/runtime/RuntimeTransferComplexTest.java b/src/test/java/org/tron/common/runtime/RuntimeTransferComplexTest.java index 04b46a8906b..625bdb39522 100644 --- a/src/test/java/org/tron/common/runtime/RuntimeTransferComplexTest.java +++ b/src/test/java/org/tron/common/runtime/RuntimeTransferComplexTest.java @@ -78,10 +78,10 @@ public void TransferTrxToContractAccountWhenDeployAContract() long fee = 100000000; long consumeUserResourcePercent = 0; - Transaction trx = TVMTestUtils.generateDeploySmartContractAndGetTransaction( + Transaction trx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( contractName, address, ABI, code, value, fee, consumeUserResourcePercent, null); byte[] contractAddress = Wallet.generateContractAddress(trx); - runtime = TVMTestUtils.processTransactionAndReturnRuntime(trx, deposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, deposit, null); Assert.assertNull(runtime.getRuntimeError()); Assert.assertEquals(dbManager.getAccountStore().get(contractAddress).getBalance(), 100); recoverDeposit(); @@ -106,10 +106,10 @@ public void TransferTrxToContractAccountFailIfNotPayable() long fee = 100000000; long consumeUserResourcePercent = 0; - Transaction trx = TVMTestUtils.generateDeploySmartContractAndGetTransaction( + Transaction trx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( contractName, address, ABI, code, value, fee, consumeUserResourcePercent, null); byte[] contractAddress = Wallet.generateContractAddress(trx); - runtime = TVMTestUtils.processTransactionAndReturnRuntime(trx, deposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, deposit, null); Assert.assertNotNull(runtime.getRuntimeError().contains("REVERT")); Assert.assertNull(dbManager.getAccountStore().get(contractAddress)); recoverDeposit(); @@ -141,21 +141,21 @@ public void TransferTrxToContractAccountWhenTriggerAContract() long transferToInitBalance = dbManager.getAccountStore().get(Hex.decode(TRANSFER_TO)) .getBalance(); - byte[] contractAddress = TVMTestUtils + byte[] contractAddress = TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, null, deposit, null); String selectorStr = "transferTo(address)"; String params = "000000000000000000000000548794500882809695a8a687866e76d4271a1abc"; //TRANSFER_TO - byte[] triggerData = TVMTestUtils.parseABI(selectorStr, params); + byte[] triggerData = TvmTestUtils.parseAbi(selectorStr, params); long triggerCallValue = 100; - Transaction transaction = TVMTestUtils + Transaction transaction = TvmTestUtils .generateTriggerSmartContractAndGetTransaction(address, contractAddress, triggerData, triggerCallValue, feeLimit); - runtime = TVMTestUtils.processTransactionAndReturnRuntime(transaction, deposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(transaction, deposit, null); Assert.assertNull(runtime.getRuntimeError()); Assert.assertEquals(dbManager.getAccountStore().get(contractAddress).getBalance(), 100 - 5); Assert.assertEquals(dbManager.getAccountStore().get(Hex.decode(TRANSFER_TO)).getBalance(), @@ -217,12 +217,12 @@ public void TransferCallValueTestWhenUsingCallAndCreate() //==================================1. testCallTransferToInCalledContract==================================== String selectorStr1 = "testCallTransferToInCalledContract(address)"; String params1 = "000000000000000000000000548794500882809695a8a687866e76d4271a1abc"; //TRANSFER_TO - byte[] triggerData1 = TVMTestUtils.parseABI(selectorStr1, params1); + byte[] triggerData1 = TvmTestUtils.parseAbi(selectorStr1, params1); - Transaction transaction1 = TVMTestUtils + Transaction transaction1 = TvmTestUtils .generateTriggerSmartContractAndGetTransaction(msgSenderAddress, callerAddress, triggerData1, triggerCallValue, feeLimit); - runtime = TVMTestUtils.processTransactionAndReturnRuntime(transaction1, deposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(transaction1, deposit, null); Assert.assertNull(runtime.getRuntimeError()); Assert.assertEquals(dbManager.getAccountStore().get(callerAddress).getBalance(), 1000); //Not changed @@ -235,12 +235,12 @@ public void TransferCallValueTestWhenUsingCallAndCreate() //==================================2. testRevertForCall ================================================= String selectorStr2 = "testRevertForCall(address)"; String params2 = "000000000000000000000000548794500882809695a8a687866e76d4271a1abc"; //TRANSFER_TO - byte[] triggerData2 = TVMTestUtils.parseABI(selectorStr2, params2); + byte[] triggerData2 = TvmTestUtils.parseAbi(selectorStr2, params2); - Transaction transaction2 = TVMTestUtils + Transaction transaction2 = TvmTestUtils .generateTriggerSmartContractAndGetTransaction(msgSenderAddress, callerAddress, triggerData2, triggerCallValue, feeLimit); - runtime = TVMTestUtils.processTransactionAndReturnRuntime(transaction2, deposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(transaction2, deposit, null); Assert.assertTrue(runtime.getRuntimeError().contains("REVERT")); Assert.assertEquals(dbManager.getAccountStore().get(callerAddress).getBalance(), 1000); //Not changed @@ -253,12 +253,12 @@ public void TransferCallValueTestWhenUsingCallAndCreate() //==================================3. testExceptionForCall ================================================= String selectorStr3 = "testExceptionForCall(address)"; String params3 = "000000000000000000000000548794500882809695a8a687866e76d4271a1abc"; //TRANSFER_TO - byte[] triggerData3 = TVMTestUtils.parseABI(selectorStr3, params3); + byte[] triggerData3 = TvmTestUtils.parseAbi(selectorStr3, params3); - Transaction transaction3 = TVMTestUtils + Transaction transaction3 = TvmTestUtils .generateTriggerSmartContractAndGetTransaction(msgSenderAddress, callerAddress, triggerData3, triggerCallValue, feeLimit); - runtime = TVMTestUtils.processTransactionAndReturnRuntime(transaction3, deposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(transaction3, deposit, null); Assert.assertTrue(runtime.getRuntimeError().contains("Invalid operation code: opCode[fe];")); Assert.assertEquals(dbManager.getAccountStore().get(callerAddress).getBalance(), 1000); //Not changed @@ -271,12 +271,12 @@ public void TransferCallValueTestWhenUsingCallAndCreate() //==================================4. testTransferToInCreatedContract ================================================= String selectorStr4 = "testTransferToInCreatedContract(address)"; String params4 = "000000000000000000000000548794500882809695a8a687866e76d4271a1abc"; //TRANSFER_TO - byte[] triggerData4 = TVMTestUtils.parseABI(selectorStr4, params4); + byte[] triggerData4 = TvmTestUtils.parseAbi(selectorStr4, params4); - Transaction transaction4 = TVMTestUtils + Transaction transaction4 = TvmTestUtils .generateTriggerSmartContractAndGetTransaction(msgSenderAddress, callerAddress, triggerData4, triggerCallValue, feeLimit); - runtime = TVMTestUtils.processTransactionAndReturnRuntime(transaction4, deposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(transaction4, deposit, null); byte[] createdAddress = convertToTronAddress( new DataWord(runtime.getResult().getHReturn()).getLast20Bytes()); Assert.assertNull(runtime.getRuntimeError()); @@ -291,12 +291,12 @@ public void TransferCallValueTestWhenUsingCallAndCreate() //==================================5. testRevertForCreate ================================================= String selectorStr5 = "testRevertForCreate(address)"; String params5 = "000000000000000000000000548794500882809695a8a687866e76d4271a1abc"; //TRANSFER_TO - byte[] triggerData5 = TVMTestUtils.parseABI(selectorStr5, params5); + byte[] triggerData5 = TvmTestUtils.parseAbi(selectorStr5, params5); - Transaction transaction5 = TVMTestUtils + Transaction transaction5 = TvmTestUtils .generateTriggerSmartContractAndGetTransaction(msgSenderAddress, callerAddress, triggerData5, triggerCallValue, feeLimit); - runtime = TVMTestUtils.processTransactionAndReturnRuntime(transaction5, deposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(transaction5, deposit, null); byte[] createdAddress2 = convertToTronAddress( new DataWord(runtime.getResult().getHReturn()).getLast20Bytes()); Assert.assertTrue(Hex.toHexString(new DataWord(createdAddress2).getLast20Bytes()) @@ -313,12 +313,12 @@ public void TransferCallValueTestWhenUsingCallAndCreate() //==================================5. testExceptionForCreate ================================================= String selectorStr6 = "testExceptionForCreate(address)"; String params6 = "000000000000000000000000548794500882809695a8a687866e76d4271a1abc"; //TRANSFER_TO - byte[] triggerData6 = TVMTestUtils.parseABI(selectorStr6, params6); + byte[] triggerData6 = TvmTestUtils.parseAbi(selectorStr6, params6); - Transaction transaction6 = TVMTestUtils + Transaction transaction6 = TvmTestUtils .generateTriggerSmartContractAndGetTransaction(msgSenderAddress, callerAddress, triggerData6, triggerCallValue, feeLimit); - runtime = TVMTestUtils.processTransactionAndReturnRuntime(transaction6, deposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(transaction6, deposit, null); byte[] createdAddress3 = convertToTronAddress( new DataWord(runtime.getResult().getHReturn()).getLast20Bytes()); Assert.assertTrue(Hex.toHexString(new DataWord(createdAddress2).getLast20Bytes()) @@ -355,7 +355,7 @@ private byte[] deployCalledContract() long feeLimit = 100000000; long consumeUserResourcePercent = 0; - byte[] contractAddress = TVMTestUtils + byte[] contractAddress = TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, null, deposit, null); @@ -409,7 +409,7 @@ private byte[] deployCallerContract(byte[] calledAddress) long value = 1000; long feeLimit = 100000000; long consumeUserResourcePercent = 0; - byte[] contractAddress = TVMTestUtils + byte[] contractAddress = TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, callerAddress, callerABI, callerCode, value, feeLimit, consumeUserResourcePercent, null, deposit, null); diff --git a/src/test/java/org/tron/common/runtime/TVMTestUtils.java b/src/test/java/org/tron/common/runtime/TvmTestUtils.java similarity index 82% rename from src/test/java/org/tron/common/runtime/TVMTestUtils.java rename to src/test/java/org/tron/common/runtime/TvmTestUtils.java index 68174d83b26..2b38c1a6ff5 100644 --- a/src/test/java/org/tron/common/runtime/TVMTestUtils.java +++ b/src/test/java/org/tron/common/runtime/TvmTestUtils.java @@ -1,7 +1,5 @@ package org.tron.common.runtime; -import static stest.tron.wallet.common.client.utils.PublicMethed.jsonStr2Abi; - import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonParser; @@ -32,6 +30,7 @@ import stest.tron.wallet.common.client.Parameter.CommonConstant; import stest.tron.wallet.common.client.WalletClient; import stest.tron.wallet.common.client.utils.AbiUtil; +import stest.tron.wallet.common.client.utils.PublicMethed; /** @@ -40,14 +39,15 @@ * commands. */ @Slf4j -public class TVMTestUtils { +public class TvmTestUtils { public static byte[] deployContractWholeProcessReturnContractAddress(String contractName, byte[] callerAddress, - String ABI, String code, long value, long feeLimit, long consumeUserResourcePercent, + String abi, String code, long value, long feeLimit, long consumeUserResourcePercent, String libraryAddressPair, DepositImpl deposit, BlockCapsule block) - throws ContractExeException, ReceiptCheckErrException, ContractValidateException, VMIllegalException { - Transaction trx = generateDeploySmartContractAndGetTransaction(contractName, callerAddress, ABI, + throws ContractExeException, ReceiptCheckErrException, + ContractValidateException, VMIllegalException { + Transaction trx = generateDeploySmartContractAndGetTransaction(contractName, callerAddress, abi, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair); processTransactionAndReturnRuntime(trx, deposit, block); return Wallet.generateContractAddress(trx); @@ -55,11 +55,12 @@ public static byte[] deployContractWholeProcessReturnContractAddress(String cont public static byte[] deployContractWholeProcessReturnContractAddress(String contractName, byte[] callerAddress, - String ABI, String code, long value, long feeLimit, long consumeUserResourcePercent, + String abi, String code, long value, long feeLimit, long consumeUserResourcePercent, String libraryAddressPair, long tokenValue, long tokenId, DepositImpl deposit, BlockCapsule block) - throws ContractExeException, ReceiptCheckErrException, ContractValidateException, VMIllegalException { - Transaction trx = generateDeploySmartContractAndGetTransaction(contractName, callerAddress, ABI, + throws ContractExeException, ReceiptCheckErrException, + ContractValidateException, VMIllegalException { + Transaction trx = generateDeploySmartContractAndGetTransaction(contractName, callerAddress, abi, code, value, feeLimit, consumeUserResourcePercent, tokenValue, tokenId, libraryAddressPair); processTransactionAndReturnRuntime(trx, deposit, block); return Wallet.generateContractAddress(trx); @@ -68,7 +69,8 @@ public static byte[] deployContractWholeProcessReturnContractAddress(String cont public static Runtime triggerContractWholeProcessReturnContractAddress(byte[] callerAddress, byte[] contractAddress, byte[] data, long callValue, long feeLimit, DepositImpl deposit, BlockCapsule block) - throws ContractExeException, ReceiptCheckErrException, ContractValidateException, VMIllegalException { + throws ContractExeException, ReceiptCheckErrException, + ContractValidateException, VMIllegalException { Transaction trx = generateTriggerSmartContractAndGetTransaction(callerAddress, contractAddress, data, callValue, feeLimit); return processTransactionAndReturnRuntime(trx, deposit, block); @@ -76,36 +78,36 @@ public static Runtime triggerContractWholeProcessReturnContractAddress(byte[] ca /** * return generated smart contract Transaction, just before we use it to broadcast and push - * transaction + * transaction. */ public static Transaction generateDeploySmartContractAndGetTransaction(String contractName, byte[] callerAddress, - String ABI, String code, long value, long feeLimit, long consumeUserResourcePercent, + String abi, String code, long value, long feeLimit, long consumeUserResourcePercent, String libraryAddressPair) { - return generateDeploySmartContractAndGetTransaction(contractName, callerAddress, ABI, code, + return generateDeploySmartContractAndGetTransaction(contractName, callerAddress, abi, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair, 0); } public static Transaction generateDeploySmartContractAndGetTransaction(String contractName, byte[] callerAddress, - String ABI, String code, long value, long feeLimit, long consumeUserResourcePercent, + String abi, String code, long value, long feeLimit, long consumeUserResourcePercent, long tokenValue, long tokenId, String libraryAddressPair) { - return generateDeploySmartContractAndGetTransaction(contractName, callerAddress, ABI, code, + return generateDeploySmartContractAndGetTransaction(contractName, callerAddress, abi, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair, 0, tokenValue, tokenId); } /** * return generated smart contract Transaction, just before we use it to broadcast and push - * transaction + * transaction. */ public static Transaction generateDeploySmartContractAndGetTransaction(String contractName, byte[] callerAddress, - String ABI, String code, long value, long feeLimit, long consumeUserResourcePercent, + String abi, String code, long value, long feeLimit, long consumeUserResourcePercent, String libraryAddressPair, long orginEngeryLimit) { - CreateSmartContract contract = buildCreateSmartContract(contractName, callerAddress, ABI, code, + CreateSmartContract contract = buildCreateSmartContract(contractName, callerAddress, abi, code, value, consumeUserResourcePercent, libraryAddressPair, orginEngeryLimit); TransactionCapsule trxCapWithoutFeeLimit = new TransactionCapsule(contract, ContractType.CreateSmartContract); @@ -121,10 +123,10 @@ public static Transaction generateDeploySmartContractAndGetTransaction(String co public static Transaction generateDeploySmartContractAndGetTransaction(String contractName, byte[] callerAddress, - String ABI, String code, long value, long feeLimit, long consumeUserResourcePercent, + String abi, String code, long value, long feeLimit, long consumeUserResourcePercent, String libraryAddressPair, long orginEngeryLimit, long tokenValue, long tokenId) { - CreateSmartContract contract = buildCreateSmartContract(contractName, callerAddress, ABI, code, + CreateSmartContract contract = buildCreateSmartContract(contractName, callerAddress, abi, code, value, consumeUserResourcePercent, libraryAddressPair, orginEngeryLimit, tokenValue, tokenId); TransactionCapsule trxCapWithoutFeeLimit = new TransactionCapsule(contract, @@ -142,11 +144,11 @@ public static Transaction generateDeploySmartContractAndGetTransaction(String co public static Transaction generateDeploySmartContractWithCreatorEnergyLimitAndGetTransaction( String contractName, byte[] callerAddress, - String ABI, String code, long value, long feeLimit, long consumeUserResourcePercent, + String abi, String code, long value, long feeLimit, long consumeUserResourcePercent, String libraryAddressPair, long creatorEnergyLimit) { CreateSmartContract contract = buildCreateSmartContractWithCreatorEnergyLimit(contractName, - callerAddress, ABI, code, + callerAddress, abi, code, value, consumeUserResourcePercent, libraryAddressPair, creatorEnergyLimit); TransactionCapsule trxCapWithoutFeeLimit = new TransactionCapsule(contract, ContractType.CreateSmartContract); @@ -161,12 +163,13 @@ public static Transaction generateDeploySmartContractWithCreatorEnergyLimitAndGe /** * use given input Transaction,deposit,block and execute TVM (for both Deploy and Trigger - * contracts) + * contracts). */ public static Runtime processTransactionAndReturnRuntime(Transaction trx, Deposit deposit, BlockCapsule block) - throws ContractExeException, ContractValidateException, ReceiptCheckErrException, VMIllegalException { + throws ContractExeException, ContractValidateException, + ReceiptCheckErrException, VMIllegalException { TransactionCapsule trxCap = new TransactionCapsule(trx); deposit.commit(); TransactionTrace trace = new TransactionTrace(trxCap, deposit.getDbManager()); @@ -182,7 +185,8 @@ public static Runtime processTransactionAndReturnRuntime(Transaction trx, public static Runtime processTransactionAndReturnRuntime(Transaction trx, Manager dbmanager, BlockCapsule block) - throws ContractExeException, ContractValidateException, ReceiptCheckErrException, VMIllegalException { + throws ContractExeException, ContractValidateException, + ReceiptCheckErrException, VMIllegalException { TransactionCapsule trxCap = new TransactionCapsule(trx); TransactionTrace trace = new TransactionTrace(trxCap, dbmanager); @@ -198,7 +202,8 @@ public static Runtime processTransactionAndReturnRuntime(Transaction trx, public static TransactionTrace processTransactionAndReturnTrace(Transaction trx, DepositImpl deposit, BlockCapsule block) - throws ContractExeException, ContractValidateException, ReceiptCheckErrException, VMIllegalException { + throws ContractExeException, ContractValidateException, + ReceiptCheckErrException, VMIllegalException { TransactionCapsule trxCap = new TransactionCapsule(trx); deposit.commit(); TransactionTrace trace = new TransactionTrace(trxCap, deposit.getDbManager()); @@ -213,50 +218,54 @@ public static TransactionTrace processTransactionAndReturnTrace(Transaction trx, } - public static TVMTestResult deployContractAndReturnTVMTestResult(String contractName, + public static TVMTestResult deployContractAndReturnTvmTestResult(String contractName, byte[] callerAddress, - String ABI, String code, long value, long feeLimit, long consumeUserResourcePercent, + String abi, String code, long value, long feeLimit, long consumeUserResourcePercent, String libraryAddressPair, Manager dbManager, BlockCapsule blockCap) - throws ContractExeException, ReceiptCheckErrException, ContractValidateException, VMIllegalException { - Transaction trx = generateDeploySmartContractAndGetTransaction(contractName, callerAddress, ABI, + throws ContractExeException, ReceiptCheckErrException, + ContractValidateException, VMIllegalException { + Transaction trx = generateDeploySmartContractAndGetTransaction(contractName, callerAddress, abi, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair); byte[] contractAddress = Wallet.generateContractAddress(trx); - return processTransactionAndReturnTVMTestResult(trx, dbManager, blockCap) + return processTransactionAndReturnTvmTestResult(trx, dbManager, blockCap) .setContractAddress(Wallet.generateContractAddress(trx)); } - public static TVMTestResult deployContractWithCreatorEnergyLimitAndReturnTVMTestResult( + public static TVMTestResult deployContractWithCreatorEnergyLimitAndReturnTvmTestResult( String contractName, byte[] callerAddress, - String ABI, String code, long value, long feeLimit, long consumeUserResourcePercent, + String abi, String code, long value, long feeLimit, long consumeUserResourcePercent, String libraryAddressPair, Manager dbManager, BlockCapsule blockCap, long creatorEnergyLimit) - throws ContractExeException, ReceiptCheckErrException, ContractValidateException, VMIllegalException { + throws ContractExeException, ReceiptCheckErrException, + ContractValidateException, VMIllegalException { Transaction trx = generateDeploySmartContractWithCreatorEnergyLimitAndGetTransaction( - contractName, callerAddress, ABI, + contractName, callerAddress, abi, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair, creatorEnergyLimit); byte[] contractAddress = Wallet.generateContractAddress(trx); - return processTransactionAndReturnTVMTestResult(trx, dbManager, blockCap) + return processTransactionAndReturnTvmTestResult(trx, dbManager, blockCap) .setContractAddress(Wallet.generateContractAddress(trx)); } - public static TVMTestResult triggerContractAndReturnTVMTestResult(byte[] callerAddress, + public static TVMTestResult triggerContractAndReturnTvmTestResult(byte[] callerAddress, byte[] contractAddress, byte[] data, long callValue, long feeLimit, Manager dbManager, BlockCapsule blockCap) - throws ContractExeException, ReceiptCheckErrException, ContractValidateException, VMIllegalException { + throws ContractExeException, ReceiptCheckErrException, + ContractValidateException, VMIllegalException { Transaction trx = generateTriggerSmartContractAndGetTransaction(callerAddress, contractAddress, data, callValue, feeLimit); - return processTransactionAndReturnTVMTestResult(trx, dbManager, blockCap) + return processTransactionAndReturnTvmTestResult(trx, dbManager, blockCap) .setContractAddress(contractAddress); } - public static TVMTestResult processTransactionAndReturnTVMTestResult(Transaction trx, + public static TVMTestResult processTransactionAndReturnTvmTestResult(Transaction trx, Manager dbManager, BlockCapsule blockCap) - throws ContractExeException, ContractValidateException, ReceiptCheckErrException, VMIllegalException { + throws ContractExeException, ContractValidateException, + ReceiptCheckErrException, VMIllegalException { TransactionCapsule trxCap = new TransactionCapsule(trx); TransactionTrace trace = new TransactionTrace(trxCap, dbManager); @@ -267,14 +276,15 @@ public static TVMTestResult processTransactionAndReturnTVMTestResult(Transaction trace.finalization(); + trace.setResult(); return new TVMTestResult(trace.getRuntime(), trace.getReceipt(), null); } public static CreateSmartContract buildCreateSmartContract(String contractName, byte[] address, - String ABI, String code, long value, long consumeUserResourcePercent, + String abiString, String code, long value, long consumeUserResourcePercent, String libraryAddressPair, long engeryLimit) { - SmartContract.ABI abi = jsonStr2ABI(ABI); + SmartContract.ABI abi = jsonStr2Abi(abiString); if (abi == null) { logger.error("abi is null"); return null; @@ -298,15 +308,15 @@ public static CreateSmartContract buildCreateSmartContract(String contractName, } builder.setBytecode(ByteString.copyFrom(byteCode)); - return CreateSmartContract.newBuilder().setOwnerAddress(ByteString.copyFrom(address)). - setNewContract(builder.build()).build(); + return CreateSmartContract.newBuilder().setOwnerAddress(ByteString.copyFrom(address)) + .setNewContract(builder.build()).build(); } public static CreateSmartContract buildCreateSmartContract(String contractName, byte[] address, - String ABI, String code, long value, long consumeUserResourcePercent, + String abiString, String code, long value, long consumeUserResourcePercent, String libraryAddressPair, long engeryLimit, long tokenValue, long tokenId) { - SmartContract.ABI abi = jsonStr2ABI(ABI); + SmartContract.ABI abi = jsonStr2Abi(abiString); if (abi == null) { logger.error("abi is null"); return null; @@ -330,9 +340,9 @@ public static CreateSmartContract buildCreateSmartContract(String contractName, } builder.setBytecode(ByteString.copyFrom(byteCode)); - return CreateSmartContract.newBuilder().setOwnerAddress(ByteString.copyFrom(address)). - setCallTokenValue(tokenValue).setTokenId(tokenId). - setNewContract(builder.build()).build(); + return CreateSmartContract.newBuilder().setOwnerAddress(ByteString.copyFrom(address)) + .setCallTokenValue(tokenValue).setTokenId(tokenId) + .setNewContract(builder.build()).build(); } /** @@ -340,20 +350,20 @@ public static CreateSmartContract buildCreateSmartContract(String contractName, */ public static CreateSmartContract buildCreateSmartContract(String contractName, byte[] address, - String ABI, String code, long value, long consumeUserResourcePercent, + String abi, String code, long value, long consumeUserResourcePercent, String libraryAddressPair) { return buildCreateSmartContract(contractName, address, - ABI, code, value, consumeUserResourcePercent, + abi, code, value, consumeUserResourcePercent, libraryAddressPair, 0); } public static CreateSmartContract buildCreateSmartContractWithCreatorEnergyLimit( String contractName, byte[] address, - String ABI, String code, long value, long consumeUserResourcePercent, + String abiString, String code, long value, long consumeUserResourcePercent, String libraryAddressPair, long creatorEnergyLimit) { - SmartContract.ABI abi = jsonStr2ABI(ABI); + SmartContract.ABI abi = jsonStr2Abi(abiString); if (abi == null) { logger.error("abi is null"); return null; @@ -377,8 +387,8 @@ public static CreateSmartContract buildCreateSmartContractWithCreatorEnergyLimit } builder.setBytecode(ByteString.copyFrom(byteCode)); - return CreateSmartContract.newBuilder().setOwnerAddress(ByteString.copyFrom(address)). - setNewContract(builder.build()).build(); + return CreateSmartContract.newBuilder().setOwnerAddress(ByteString.copyFrom(address)) + .setNewContract(builder.build()).build(); } @@ -498,7 +508,7 @@ private static SmartContract.ABI.Entry.StateMutabilityType getStateMutability( } } - public static SmartContract.ABI jsonStr2ABI(String jsonStr) { + public static SmartContract.ABI jsonStr2Abi(String jsonStr) { if (jsonStr == null) { return null; } @@ -509,22 +519,22 @@ public static SmartContract.ABI jsonStr2ABI(String jsonStr) { SmartContract.ABI.Builder abiBuilder = SmartContract.ABI.newBuilder(); for (int index = 0; index < jsonRoot.size(); index++) { JsonElement abiItem = jsonRoot.get(index); - boolean anonymous = abiItem.getAsJsonObject().get("anonymous") != null && - abiItem.getAsJsonObject().get("anonymous").getAsBoolean(); - boolean constant = abiItem.getAsJsonObject().get("constant") != null && - abiItem.getAsJsonObject().get("constant").getAsBoolean(); - String name = abiItem.getAsJsonObject().get("name") != null ? - abiItem.getAsJsonObject().get("name").getAsString() : null; - JsonArray inputs = abiItem.getAsJsonObject().get("inputs") != null ? - abiItem.getAsJsonObject().get("inputs").getAsJsonArray() : null; - JsonArray outputs = abiItem.getAsJsonObject().get("outputs") != null ? - abiItem.getAsJsonObject().get("outputs").getAsJsonArray() : null; - String type = abiItem.getAsJsonObject().get("type") != null ? - abiItem.getAsJsonObject().get("type").getAsString() : null; - boolean payable = abiItem.getAsJsonObject().get("payable") != null && - abiItem.getAsJsonObject().get("payable").getAsBoolean(); - String stateMutability = abiItem.getAsJsonObject().get("stateMutability") != null ? - abiItem.getAsJsonObject().get("stateMutability").getAsString() : null; + boolean anonymous = abiItem.getAsJsonObject().get("anonymous") != null + && abiItem.getAsJsonObject().get("anonymous").getAsBoolean(); + final boolean constant = abiItem.getAsJsonObject().get("constant") != null + && abiItem.getAsJsonObject().get("constant").getAsBoolean(); + final String name = abiItem.getAsJsonObject().get("name") != null + ? abiItem.getAsJsonObject().get("name").getAsString() : null; + JsonArray inputs = abiItem.getAsJsonObject().get("inputs") != null + ? abiItem.getAsJsonObject().get("inputs").getAsJsonArray() : null; + final JsonArray outputs = abiItem.getAsJsonObject().get("outputs") != null + ? abiItem.getAsJsonObject().get("outputs").getAsJsonArray() : null; + String type = abiItem.getAsJsonObject().get("type") != null + ? abiItem.getAsJsonObject().get("type").getAsString() : null; + final boolean payable = abiItem.getAsJsonObject().get("payable") != null + && abiItem.getAsJsonObject().get("payable").getAsBoolean(); + final String stateMutability = abiItem.getAsJsonObject().get("stateMutability") != null + ? abiItem.getAsJsonObject().get("stateMutability").getAsString() : null; if (type == null) { logger.error("No type!"); return null; @@ -545,8 +555,8 @@ public static SmartContract.ABI jsonStr2ABI(String jsonStr) { if (null != inputs) { for (int j = 0; j < inputs.size(); j++) { JsonElement inputItem = inputs.get(j); - if (inputItem.getAsJsonObject().get("name") == null || - inputItem.getAsJsonObject().get("type") == null) { + if (inputItem.getAsJsonObject().get("name") == null + || inputItem.getAsJsonObject().get("type") == null) { logger.error("Input argument invalid due to no name or no type!"); return null; } @@ -566,8 +576,8 @@ public static SmartContract.ABI jsonStr2ABI(String jsonStr) { if (outputs != null) { for (int k = 0; k < outputs.size(); k++) { JsonElement outputItem = outputs.get(k); - if (outputItem.getAsJsonObject().get("name") == null || - outputItem.getAsJsonObject().get("type") == null) { + if (outputItem.getAsJsonObject().get("name") == null + || outputItem.getAsJsonObject().get("type") == null) { logger.error("Output argument invalid due to no name or no type!"); return null; } @@ -595,7 +605,7 @@ public static SmartContract.ABI jsonStr2ABI(String jsonStr) { } - public static byte[] parseABI(String selectorStr, String params) { + public static byte[] parseAbi(String selectorStr, String params) { if (params == null) { params = ""; } @@ -609,7 +619,7 @@ public static CreateSmartContract createSmartContract(byte[] owner, String contr String abiString, String code, long value, long consumeUserResourcePercent) { Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - SmartContract.ABI abi = jsonStr2Abi(abiString); + SmartContract.ABI abi = PublicMethed.jsonStr2Abi(abiString); if (abi == null) { return null; } diff --git a/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeTest.java b/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeTest.java index 86beabcc105..998934b3674 100644 --- a/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeTest.java +++ b/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeTest.java @@ -27,7 +27,7 @@ import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.Runtime; import org.tron.common.runtime.RuntimeImpl; -import org.tron.common.runtime.TVMTestUtils; +import org.tron.common.runtime.TvmTestUtils; import org.tron.common.runtime.vm.program.invoke.ProgramInvokeFactoryImpl; import org.tron.common.storage.DepositImpl; import org.tron.common.utils.FileUtil; @@ -135,7 +135,7 @@ public void testSuccess() { .get(Wallet.decodeFromBase58Check(TriggerOwnerAddress)); long energy = triggerOwner.getEnergyUsage(); long balance = triggerOwner.getBalance(); - TriggerSmartContract triggerContract = TVMTestUtils.createTriggerContract(contractAddress, + TriggerSmartContract triggerContract = TvmTestUtils.createTriggerContract(contractAddress, "fibonacciNotify(uint256)", "500000", false, 0, Wallet.decodeFromBase58Check(TriggerOwnerAddress)); Transaction transaction = Transaction.newBuilder().setRawData(raw.newBuilder().addContract( @@ -178,7 +178,7 @@ private byte[] createContract() String contractName = "Fibonacci3"; String code = "608060405234801561001057600080fd5b506101ba806100206000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633c7fdc701461005157806361047ff414610092575b600080fd5b34801561005d57600080fd5b5061007c600480360381019080803590602001909291905050506100d3565b6040518082815260200191505060405180910390f35b34801561009e57600080fd5b506100bd60048036038101908080359060200190929190505050610124565b6040518082815260200191505060405180910390f35b60006100de82610124565b90507f71e71a8458267085d5ab16980fd5f114d2d37f232479c245d523ce8d23ca40ed8282604051808381526020018281526020019250505060405180910390a1919050565b60008060008060008086141561013d5760009450610185565b600186141561014f5760019450610185565b600093506001925060009150600290505b85811115156101815782840191508293508192508080600101915050610160565b8194505b505050509190505600a165627a7a7230582071f3cf655137ce9dc32d3307fb879e65f3960769282e6e452a5f0023ea046ed20029"; String abi = "[{\"constant\":false,\"inputs\":[{\"name\":\"number\",\"type\":\"uint256\"}],\"name\":\"fibonacciNotify\",\"outputs\":[{\"name\":\"result\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"number\",\"type\":\"uint256\"}],\"name\":\"fibonacci\",\"outputs\":[{\"name\":\"result\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"input\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"result\",\"type\":\"uint256\"}],\"name\":\"Notify\",\"type\":\"event\"}]"; - CreateSmartContract smartContract = TVMTestUtils.createSmartContract( + CreateSmartContract smartContract = TvmTestUtils.createSmartContract( Wallet.decodeFromBase58Check(OwnerAddress), contractName, abi, code, 0, 100); Transaction transaction = Transaction.newBuilder().setRawData(raw.newBuilder().addContract( Contract.newBuilder().setParameter(Any.pack(smartContract)) diff --git a/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java b/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java index 5fe6ad55390..d9317b82da8 100644 --- a/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java +++ b/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeOutOfTimeWithCheckTest.java @@ -27,7 +27,7 @@ import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.Runtime; import org.tron.common.runtime.RuntimeImpl; -import org.tron.common.runtime.TVMTestUtils; +import org.tron.common.runtime.TvmTestUtils; import org.tron.common.runtime.vm.program.invoke.ProgramInvokeFactoryImpl; import org.tron.common.storage.DepositImpl; import org.tron.common.utils.FileUtil; @@ -136,7 +136,7 @@ public void testSuccess() { .get(Wallet.decodeFromBase58Check(TriggerOwnerAddress)); long energy = triggerOwner.getEnergyUsage(); long balance = triggerOwner.getBalance(); - TriggerSmartContract triggerContract = TVMTestUtils.createTriggerContract(contractAddress, + TriggerSmartContract triggerContract = TvmTestUtils.createTriggerContract(contractAddress, "fibonacciNotify(uint256)", "100001", false, 0, Wallet.decodeFromBase58Check(TriggerOwnerAddress)); Transaction transaction = Transaction.newBuilder().setRawData(raw.newBuilder().addContract( @@ -182,7 +182,7 @@ private byte[] createContract() String contractName = "Fibonacci"; String code = "608060405234801561001057600080fd5b506101ba806100206000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633c7fdc701461005157806361047ff414610092575b600080fd5b34801561005d57600080fd5b5061007c600480360381019080803590602001909291905050506100d3565b6040518082815260200191505060405180910390f35b34801561009e57600080fd5b506100bd60048036038101908080359060200190929190505050610124565b6040518082815260200191505060405180910390f35b60006100de82610124565b90507f71e71a8458267085d5ab16980fd5f114d2d37f232479c245d523ce8d23ca40ed8282604051808381526020018281526020019250505060405180910390a1919050565b60008060008060008086141561013d5760009450610185565b600186141561014f5760019450610185565b600093506001925060009150600290505b85811115156101815782840191508293508192508080600101915050610160565b8194505b505050509190505600a165627a7a7230582071f3cf655137ce9dc32d3307fb879e65f3960769282e6e452a5f0023ea046ed20029"; String abi = "[{\"constant\":false,\"inputs\":[{\"name\":\"number\",\"type\":\"uint256\"}],\"name\":\"fibonacciNotify\",\"outputs\":[{\"name\":\"result\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"number\",\"type\":\"uint256\"}],\"name\":\"fibonacci\",\"outputs\":[{\"name\":\"result\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"input\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"result\",\"type\":\"uint256\"}],\"name\":\"Notify\",\"type\":\"event\"}]"; - CreateSmartContract smartContract = TVMTestUtils.createSmartContract( + CreateSmartContract smartContract = TvmTestUtils.createSmartContract( Wallet.decodeFromBase58Check(OwnerAddress), contractName, abi, code, 0, 100); Transaction transaction = Transaction.newBuilder().setRawData(raw.newBuilder().addContract( Contract.newBuilder().setParameter(Any.pack(smartContract)) diff --git a/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java b/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java index 153cc9236da..3eccc07c9e3 100644 --- a/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java +++ b/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java @@ -27,7 +27,7 @@ import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.Runtime; import org.tron.common.runtime.RuntimeImpl; -import org.tron.common.runtime.TVMTestUtils; +import org.tron.common.runtime.TvmTestUtils; import org.tron.common.runtime.vm.program.invoke.ProgramInvokeFactoryImpl; import org.tron.common.storage.DepositImpl; import org.tron.common.utils.FileUtil; @@ -141,7 +141,7 @@ public void testSuccess() { AccountCapsule triggerOwner = dbManager.getAccountStore() .get(Wallet.decodeFromBase58Check(TriggerOwnerAddress)); long energy = triggerOwner.getEnergyUsage(); - TriggerSmartContract triggerContract = TVMTestUtils.createTriggerContract(contractAddress, + TriggerSmartContract triggerContract = TvmTestUtils.createTriggerContract(contractAddress, "setCoin(uint256)", "3", false, 0, Wallet.decodeFromBase58Check(TriggerOwnerAddress)); Transaction transaction = Transaction.newBuilder().setRawData(raw.newBuilder().addContract( @@ -174,7 +174,7 @@ public void testSuccess() { public void testSuccessNoBandd() { try { byte[] contractAddress = createContract(); - TriggerSmartContract triggerContract = TVMTestUtils.createTriggerContract(contractAddress, + TriggerSmartContract triggerContract = TvmTestUtils.createTriggerContract(contractAddress, "setCoin(uint256)", "50", false, 0, Wallet.decodeFromBase58Check(TriggerOwnerTwoAddress)); Transaction transaction = Transaction.newBuilder().setRawData(raw.newBuilder().addContract( @@ -218,7 +218,7 @@ private byte[] createContract() String contractName = "foriContract"; String code = "608060405234801561001057600080fd5b50610105806100206000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680637bb98a6814604e578063866edb47146076575b600080fd5b348015605957600080fd5b50606060a0565b6040518082815260200191505060405180910390f35b348015608157600080fd5b50609e6004803603810190808035906020019092919050505060a6565b005b60005481565b60008090505b8181101560d55760008081548092919060010191905055600081905550808060010191505060ac565b50505600a165627a7a72305820f4020a69fb8504d7db776726b19e5101c3216413d7ab8e91a11c4f55f772caed0029"; String abi = "[{\"constant\":true,\"inputs\":[],\"name\":\"balances\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"receiver\",\"type\":\"uint256\"}],\"name\":\"setCoin\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"; - CreateSmartContract smartContract = TVMTestUtils.createSmartContract( + CreateSmartContract smartContract = TvmTestUtils.createSmartContract( Wallet.decodeFromBase58Check(OwnerAddress), contractName, abi, code, 0, 100); Transaction transaction = Transaction.newBuilder().setRawData(raw.newBuilder().addContract( Contract.newBuilder().setParameter(Any.pack(smartContract)) diff --git a/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeWithCheckTest.java b/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeWithCheckTest.java index c7872184216..38eb8bd9760 100644 --- a/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeWithCheckTest.java +++ b/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeWithCheckTest.java @@ -27,7 +27,7 @@ import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.Runtime; import org.tron.common.runtime.RuntimeImpl; -import org.tron.common.runtime.TVMTestUtils; +import org.tron.common.runtime.TvmTestUtils; import org.tron.common.runtime.vm.program.invoke.ProgramInvokeFactoryImpl; import org.tron.common.storage.DepositImpl; import org.tron.common.utils.FileUtil; @@ -144,7 +144,7 @@ public void testSuccess() { .get(Wallet.decodeFromBase58Check(TriggerOwnerAddress)); long energy = triggerOwner.getEnergyUsage(); long balance = triggerOwner.getBalance(); - TriggerSmartContract triggerContract = TVMTestUtils.createTriggerContract(contractAddress, + TriggerSmartContract triggerContract = TvmTestUtils.createTriggerContract(contractAddress, "fibonacciNotify(uint256)", "7000", false, 0, Wallet.decodeFromBase58Check(TriggerOwnerAddress)); Transaction transaction = Transaction.newBuilder().setRawData(raw.newBuilder().addContract( @@ -182,7 +182,7 @@ public void testSuccess() { public void testSuccessNoBandWidth() { try { byte[] contractAddress = createContract(); - TriggerSmartContract triggerContract = TVMTestUtils.createTriggerContract(contractAddress, + TriggerSmartContract triggerContract = TvmTestUtils.createTriggerContract(contractAddress, "fibonacciNotify(uint256)", "50", false, 0, Wallet.decodeFromBase58Check(TriggerOwnerTwoAddress)); Transaction transaction = Transaction.newBuilder().setRawData(raw.newBuilder().addContract( @@ -229,7 +229,7 @@ private byte[] createContract() String contractName = "Fibonacci"; String code = "608060405234801561001057600080fd5b506101ba806100206000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633c7fdc701461005157806361047ff414610092575b600080fd5b34801561005d57600080fd5b5061007c600480360381019080803590602001909291905050506100d3565b6040518082815260200191505060405180910390f35b34801561009e57600080fd5b506100bd60048036038101908080359060200190929190505050610124565b6040518082815260200191505060405180910390f35b60006100de82610124565b90507f71e71a8458267085d5ab16980fd5f114d2d37f232479c245d523ce8d23ca40ed8282604051808381526020018281526020019250505060405180910390a1919050565b60008060008060008086141561013d5760009450610185565b600186141561014f5760019450610185565b600093506001925060009150600290505b85811115156101815782840191508293508192508080600101915050610160565b8194505b505050509190505600a165627a7a7230582071f3cf655137ce9dc32d3307fb879e65f3960769282e6e452a5f0023ea046ed20029"; String abi = "[{\"constant\":false,\"inputs\":[{\"name\":\"number\",\"type\":\"uint256\"}],\"name\":\"fibonacciNotify\",\"outputs\":[{\"name\":\"result\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"number\",\"type\":\"uint256\"}],\"name\":\"fibonacci\",\"outputs\":[{\"name\":\"result\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"input\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"result\",\"type\":\"uint256\"}],\"name\":\"Notify\",\"type\":\"event\"}]"; - CreateSmartContract smartContract = TVMTestUtils.createSmartContract( + CreateSmartContract smartContract = TvmTestUtils.createSmartContract( Wallet.decodeFromBase58Check(OwnerAddress), contractName, abi, code, 0, 100); Transaction transaction = Transaction.newBuilder().setRawData(raw.newBuilder().addContract( Contract.newBuilder().setParameter(Any.pack(smartContract)) diff --git a/src/test/java/org/tron/common/runtime/vm/ChargeTest.java b/src/test/java/org/tron/common/runtime/vm/ChargeTest.java index f56054f7f0e..f19e4a17203 100644 --- a/src/test/java/org/tron/common/runtime/vm/ChargeTest.java +++ b/src/test/java/org/tron/common/runtime/vm/ChargeTest.java @@ -12,7 +12,7 @@ import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.TVMTestResult; -import org.tron.common.runtime.TVMTestUtils; +import org.tron.common.runtime.TvmTestUtils; import org.tron.common.storage.DepositImpl; import org.tron.common.utils.FileUtil; import org.tron.core.Constant; @@ -82,8 +82,8 @@ public void testOverflow() String code = "608060405234801561001057600080fd5b50610100806100206000396000f300608060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680638040cac4146044575b600080fd5b604a604c565b005b6000678ac7230489e80000605d607f565b6040518091039082f0801580156077573d6000803e3d6000fd5b509050905050565b60405160468061008f833901905600608060405260358060116000396000f3006080604052600080fd00a165627a7a723058201738d6aa899dc00d4e99de944eb74d30a9ba1fcae37b99dc6299d95e992ca8b40029a165627a7a7230582068390137ba70dfc460810603eba8500b050ed3cd01e66f55ec07d387ec1cd2750029"; String libraryAddressPair = null; - TVMTestResult result = TVMTestUtils - .deployContractAndReturnTVMTestResult(contractName, address, ABI, code, + TVMTestResult result = TvmTestUtils + .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair, dbManager, null); @@ -95,9 +95,9 @@ public void testOverflow() byte[] contractAddress = result.getContractAddress(); /* ====================================================================== */ - byte[] triggerData = TVMTestUtils.parseABI("testOverflow()", ""); - result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + byte[] triggerData = TvmTestUtils.parseAbi("testOverflow()", ""); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, 20_000_000_000L, feeLimit, dbManager, null); long expectEnergyUsageTotal2 = feeLimit / 100; @@ -138,8 +138,8 @@ public void testNegative() String code = "608060405234801561001057600080fd5b50610154806100206000396000f300608060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680638f7d8a1c146044575b600080fd5b604a604c565b005b6000807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff91507f3a26492830c137b6cedfdd0e23db0e9c7c214e4fd1de32de8ceece1678b771b3826040518082815260200191505060405180910390a18160b060d3565b6040518091039082f08015801560ca573d6000803e3d6000fd5b50905090505050565b6040516046806100e3833901905600608060405260358060116000396000f3006080604052600080fd00a165627a7a72305820ef54aac72efff56dbe894e7218d009a87368bb70338bb385db5d3dec9927bc2c0029a165627a7a723058201620679ac2ae640d0a6c26e9cb4523e98eb0de8fff26975c5bb4c7fda1c98d720029"; String libraryAddressPair = null; - TVMTestResult result = TVMTestUtils - .deployContractAndReturnTVMTestResult(contractName, address, ABI, code, + TVMTestResult result = TvmTestUtils + .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair, dbManager, null); @@ -151,9 +151,9 @@ public void testNegative() byte[] contractAddress = result.getContractAddress(); /* ======================================CALL testNegative() with 0 callvalue ================================ */ - byte[] triggerData = TVMTestUtils.parseABI("testNegative()", ""); - result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + byte[] triggerData = TvmTestUtils.parseAbi("testNegative()", ""); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, value, feeLimit, dbManager, null); long expectEnergyUsageTotal2 = feeLimit / 100; @@ -166,9 +166,9 @@ public void testNegative() /* ======================================CALL testNegative() with -100 callvalue ================================ */ - triggerData = TVMTestUtils.parseABI("testNegative()", ""); - result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + triggerData = TvmTestUtils.parseAbi("testNegative()", ""); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, -100, feeLimit, dbManager, null); long expectEnergyUsageTotal3 = feeLimit / 100; @@ -216,8 +216,8 @@ public void testCallDepth() String code = "608060405234801561001057600080fd5b50610174806100206000396000f3006080604052600436106100325763ffffffff60e060020a6000350416633a3c47188114610037578063eede0f0114610051575b600080fd5b34801561004357600080fd5b5061004f600435610069565b005b34801561005d57600080fd5b5061004f6004356100d7565b60008113156100d45730633a3c47186107d05a03600184036040518363ffffffff1660e060020a02815260040180828152602001915050600060405180830381600088803b1580156100ba57600080fd5b5087f11580156100ce573d6000803e3d6000fd5b50505050505b50565b3073ffffffffffffffffffffffffffffffffffffffff16633a3c4718826040518263ffffffff1660e060020a02815260040180828152602001915050600060405180830381600087803b15801561012d57600080fd5b505af1158015610141573d6000803e3d6000fd5b50505050505600a165627a7a72305820510367f4437b1af16931cacc744eb6f3102d72f0c369aa795a4dc49a7f90a3e90029"; String libraryAddressPair = null; - TVMTestResult result = TVMTestUtils - .deployContractAndReturnTVMTestResult(contractName, address, ABI, code, + TVMTestResult result = TvmTestUtils + .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair, dbManager, null); @@ -230,10 +230,10 @@ public void testCallDepth() /* ====================================================================== */ String params = "0000000000000000000000000000000000000000000000000000000000002710"; - // byte[] triggerData = TVMTestUtils.parseABI("CallstackExploit(int)", params); - byte[] triggerData = TVMTestUtils.parseABI("Call(int256)", params); - result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + // byte[] triggerData = TvmTestUtils.parseAbi("CallstackExploit(int)", params); + byte[] triggerData = TvmTestUtils.parseAbi("Call(int256)", params); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, value, feeLimit, dbManager, null); long expectEnergyUsageTotal2 = 27743; @@ -299,8 +299,8 @@ public void testCallDepthAndWidth() String code = "608060405261000c61005b565b604051809103906000f080158015610028573d6000803e3d6000fd5b5060008054600160a060020a031916600160a060020a039290921691909117905534801561005557600080fd5b5061006b565b604051610265806102c683390190565b61024c8061007a6000396000f30060806040526004361061004b5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166370ed9d828114610050578063f84df1931461006a575b600080fd5b34801561005c57600080fd5b50610068600435610082565b005b34801561007657600080fd5b50610068600435610109565b600081111561010657306370ed9d826107d05a03600184036040518363ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600088803b1580156100ec57600080fd5b5087f1158015610100573d6000803e3d6000fd5b50505050505b50565b60005b8181101561021c57604080517f70ed9d82000000000000000000000000000000000000000000000000000000008152601483016004820152905130916370ed9d8291602480830192600092919082900301818387803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060008054604080517ff84df193000000000000000000000000000000000000000000000000000000008152600a87016004820152905173ffffffffffffffffffffffffffffffffffffffff909216945063f84df1939350602480820193929182900301818387803b1580156101f857600080fd5b505af115801561020c573d6000803e3d6000fd5b50506001909201915061010c9050565b50505600a165627a7a72305820ad701f54dc539d976cc2af0443d5d190dbe727ce2e24d66f3e2390dfd79859640029608060405234801561001057600080fd5b50610245806100206000396000f30060806040526004361061004b5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166370ed9d828114610050578063f84df1931461006a575b600080fd5b34801561005c57600080fd5b50610068600435610082565b005b34801561007657600080fd5b50610068600435610109565b600081111561010657306370ed9d826107d05a03600184036040518363ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600088803b1580156100ec57600080fd5b5087f1158015610100573d6000803e3d6000fd5b50505050505b50565b60006014821161018a57604080517f70ed9d82000000000000000000000000000000000000000000000000000000008152601484016004820152905130916370ed9d8291602480830192600092919082900301818387803b15801561016d57600080fd5b505af1158015610181573d6000803e3d6000fd5b50505050610215565b5060005b8181101561021557604080517ff84df193000000000000000000000000000000000000000000000000000000008152601319830160048201529051309163f84df19391602480830192600092919082900301818387803b1580156101f157600080fd5b505af1158015610205573d6000803e3d6000fd5b50506001909201915061018e9050565b50505600a165627a7a72305820a9e7e1401001d6c131ebf4727fbcedede08d16416dc0447cef60e0b9516c6a260029"; String libraryAddressPair = null; - TVMTestResult result = TVMTestUtils - .deployContractAndReturnTVMTestResult(contractName, address, ABI, code, + TVMTestResult result = TvmTestUtils + .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair, dbManager, null); @@ -313,10 +313,10 @@ public void testCallDepthAndWidth() /* ====================================================================== */ String params = "000000000000000000000000000000000000000000000000000000000000000a"; - // byte[] triggerData = TVMTestUtils.parseABI("CallstackExploit(int)", params); - byte[] triggerData = TVMTestUtils.parseABI("Call(uint256)", params); - result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + // byte[] triggerData = TvmTestUtils.parseAbi("CallstackExploit(int)", params); + byte[] triggerData = TvmTestUtils.parseAbi("Call(uint256)", params); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, value, feeLimit, dbManager, null); long expectEnergyUsageTotal2 = 243698; @@ -341,8 +341,8 @@ public void testCreateDepthAndWidth() String code = "608060405234801561001057600080fd5b506103f0806100206000396000f3006080604052600436106100405763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663b505dee58114610045575b600080fd5b34801561005157600080fd5b5061005d60043561005f565b005b6000805b828210156101255761007361012a565b604051809103906000f08015801561008f573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff1663da6d107a836040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600087803b15801561010157600080fd5b505af1158015610115573d6000803e3d6000fd5b5050600190930192506100639050565b505050565b60405161028a8061013b833901905600608060405234801561001057600080fd5b5061026a806100206000396000f3006080604052600436106100405763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663da6d107a8114610045575b600080fd5b34801561005157600080fd5b5061005d60043561005f565b005b60008082111561010f573063da6d107a6107d05a03600185036040518363ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600088803b1580156100ca57600080fd5b5087f11580156100de573d6000803e3d6000fd5b50505050506100eb61013b565b604051809103906000f080158015610107573d6000803e3d6000fd5b509050610137565b61011761013b565b604051809103906000f080158015610133573d6000803e3d6000fd5b5090505b5050565b60405160f48061014b8339019056006080604052348015600f57600080fd5b506000805b6064821015604a5760226050565b604051809103906000f080158015603d573d6000803e3d6000fd5b5060019092019190506014565b5050605f565b6040516052806100a283390190565b60358061006d6000396000f3006080604052600080fd00a165627a7a723058203565a8abc553526f8113ab8a3f432963d88cee07cafce0ebfc61173d3797b84700296080604052348015600f57600080fd5b50603580601d6000396000f3006080604052600080fd00a165627a7a723058204855bba321c7dee00dfa91caa8926cf07c38c541a11ba36d3b2a4687acaa909c0029a165627a7a7230582093af601a9196cffc9bf82bcae83557d7f5aedeec639129c27826f38c1e2a2ea00029a165627a7a7230582071d51c39c93b0aba5baeacea0b2bd5ca5342d028bb834046eca92975a3517a4c0029"; String libraryAddressPair = null; - TVMTestResult result = TVMTestUtils - .deployContractAndReturnTVMTestResult(contractName, address, ABI, code, + TVMTestResult result = TvmTestUtils + .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair, dbManager, null); @@ -355,10 +355,10 @@ public void testCreateDepthAndWidth() /* ====================================================================== */ String params = "0000000000000000000000000000000000000000000000000000000000000001"; - // byte[] triggerData = TVMTestUtils.parseABI("CallstackExploit(int)", params); - byte[] triggerData = TVMTestUtils.parseABI("testCreate(uint256)", params); - result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + // byte[] triggerData = TvmTestUtils.parseAbi("CallstackExploit(int)", params); + byte[] triggerData = TvmTestUtils.parseAbi("testCreate(uint256)", params); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, value, feeLimit, dbManager, null); long expectEnergyUsageTotal2 = 4481164; diff --git a/src/test/java/org/tron/common/runtime/vm/Create2Test.java b/src/test/java/org/tron/common/runtime/vm/Create2Test.java new file mode 100644 index 00000000000..ed215e715da --- /dev/null +++ b/src/test/java/org/tron/common/runtime/vm/Create2Test.java @@ -0,0 +1,129 @@ +package org.tron.common.runtime.vm; + +import java.util.Arrays; +import java.util.Collections; +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; +import org.spongycastle.util.encoders.Hex; +import org.testng.Assert; +import org.tron.common.runtime.TVMTestResult; +import org.tron.common.runtime.TvmTestUtils; +import org.tron.common.runtime.config.VMConfig; +import org.tron.common.runtime.utils.MUtil; +import org.tron.core.Wallet; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; +import org.tron.core.exception.ReceiptCheckErrException; +import org.tron.core.exception.VMIllegalException; +import org.tron.protos.Protocol.Transaction; +import stest.tron.wallet.common.client.utils.AbiUtil; +import stest.tron.wallet.common.client.utils.DataWord; + +@Slf4j +public class Create2Test extends VMTestBase { +/* +pragma solidity 0.5.0; +contract Factory { + event Deployed(address addr, uint256 salt); + function deploy(bytes memory code, uint256 salt) public returns(address){ + address addr; + assembly { + addr := create2(0, add(code, 0x20), mload(code), salt) + if iszero(extcodesize(addr)) { + revert(0, 0) + } + } + emit Deployed(addr, salt); + return addr; + } +} + + + +contract TestConstract { + uint public i; + constructor () public { + } + function plusOne() public returns(uint){ + i++; + } +} + */ + + /* +contract:TestConstract +deploy script: +deploycontract TestConstract_0.5.0 [{"constant":false,"inputs":[],"name":"plusOne","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"i","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"}] 608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b5060d7806100396000396000f3fe608060405260043610602c5760003560e01c63ffffffff16806368e5c066146031578063e5aa3d5814606d575b600080fd5b348015603c57600080fd5b50d38015604857600080fd5b50d28015605457600080fd5b50605b6097565b60408051918252519081900360200190f35b348015607857600080fd5b50d38015608457600080fd5b50d28015609057600080fd5b50605b60a5565b600080546001019081905590565b6000548156fea165627a7a72305820c637cddbfa24b6530000f2e54d90e0f6c15907835674109287f64303446f9afb0029 # # false 1000000000 100 10000000 0 0 # +tirgger script: +triggercontract Txxxxxxxxxxx plusOne() # false 1000000000 0 0 # +triggercontract Txxxxxxxxxxx i() # false 1000000000 0 0 # + + +contract:Factory +deploy script: +deploycontract Factory_0.5.0 [{"constant":false,"inputs":[{"name":"code","type":"bytes"},{"name":"salt","type":"uint256"}],"name":"deploy","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"addr","type":"address"},{"indexed":false,"name":"salt","type":"uint256"}],"name":"Deployed","type":"event"}] 608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b506101c18061003a6000396000f3fe6080604052600436106100245760003560e01c63ffffffff1680639c4ae2d014610029575b600080fd5b34801561003557600080fd5b50d3801561004257600080fd5b50d2801561004f57600080fd5b506100f86004803603604081101561006657600080fd5b81019060208101813564010000000081111561008157600080fd5b82018360208201111561009357600080fd5b803590602001918460018302840111640100000000831117156100b557600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505091359250610121915050565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b600080828451602086016000f59050803b151561013d57600080fd5b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810185905281517fb03c53b28e78a88e31607a27e1fa48234dce28d5d9d9ec7b295aeb02e674a1e1929181900390910190a1939250505056fea165627a7a7230582079653f6506bd7d3bdf4954ec98c452c5455d2b11444642db00b38fa422b25a650029 # # false 1000000000 100 10000000 0 0 # +tirgger script: +triggercontract Txxxxxxxxxxx deploy(bytes,uint256) bytes,uint256 false 1000000000 0 0 # + + + +*/ + + @Test + public void testCreate2() + throws ContractExeException, ReceiptCheckErrException, VMIllegalException, ContractValidateException { + VMConfig.initAllowTvmTransferTrc10(1); + VMConfig.initAllowTvmConstantinople(1); + String contractName = "Factory_0"; + byte[] address = Hex.decode(OWNER_ADDRESS); + String ABI = "[{\"constant\":false,\"inputs\":[{\"name\":\"code\",\"type\":\"bytes\"},{\"name\":\"salt\",\"type\":\"uint256\"}],\"name\":\"deploy\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"addr\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"salt\",\"type\":\"uint256\"}],\"name\":\"Deployed\",\"type\":\"event\"}]"; + String factoryCode = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b506101c18061003a6000396000f3fe6080604052600436106100245760003560e01c63ffffffff1680639c4ae2d014610029575b600080fd5b34801561003557600080fd5b50d3801561004257600080fd5b50d2801561004f57600080fd5b506100f86004803603604081101561006657600080fd5b81019060208101813564010000000081111561008157600080fd5b82018360208201111561009357600080fd5b803590602001918460018302840111640100000000831117156100b557600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505091359250610121915050565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b600080828451602086016000f59050803b151561013d57600080fd5b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810185905281517fb03c53b28e78a88e31607a27e1fa48234dce28d5d9d9ec7b295aeb02e674a1e1929181900390910190a1939250505056fea165627a7a7230582079653f6506bd7d3bdf4954ec98c452c5455d2b11444642db00b38fa422b25a650029"; + String testCode = "608060405234801561001057600080fd5b50d3801561001d57600080fd5b50d2801561002a57600080fd5b5060d7806100396000396000f3fe608060405260043610602c5760003560e01c63ffffffff16806368e5c066146031578063e5aa3d5814606d575b600080fd5b348015603c57600080fd5b50d38015604857600080fd5b50d28015605457600080fd5b50605b6097565b60408051918252519081900360200190f35b348015607857600080fd5b50d38015608457600080fd5b50d28015609057600080fd5b50605b60a5565b600080546001019081905590565b6000548156fea165627a7a72305820c637cddbfa24b6530000f2e54d90e0f6c15907835674109287f64303446f9afb0029"; + long value = 0; + long fee = 100000000; + long consumeUserResourcePercent = 0; + String methodSign = "deploy(bytes,uint256)"; + + // deploy contract + Transaction trx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( + contractName, address, ABI, factoryCode, value, fee, consumeUserResourcePercent, null); + byte[] factoryAddress = Wallet.generateContractAddress(trx); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootDeposit, null); + Assert.assertNull(runtime.getRuntimeError()); + + + // Trigger contract method: deploy(bytes,uint) + long salt = 100L; + String hexInput = AbiUtil.parseMethod(methodSign, Arrays.asList(testCode, salt)); + TVMTestResult result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), + factoryAddress, Hex.decode(hexInput), 0, fee, manager, null); + Assert.assertNull(result.getRuntime().getRuntimeError()); + + byte[] returnValue = result.getRuntime().getResult().getHReturn(); + byte[] actualContract = MUtil.convertToTronAddress(Arrays.copyOfRange(returnValue, 12, 32)); + byte[] expectedContract = Wallet.generateContractAddress2(address, new DataWord(salt).getData(), Hex.decode(testCode)); + // check deployed contract + Assert.assertEquals(actualContract, expectedContract); + + // trigger deployed contract + String methodToTrigger = "plusOne()"; + for (int i = 1; i < 3; i++) { + hexInput = AbiUtil.parseMethod(methodToTrigger, Collections.emptyList()); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), + actualContract, Hex.decode(hexInput), 0, fee, manager, null); + Assert.assertNull(result.getRuntime().getRuntimeError()); + Assert.assertEquals(result.getRuntime().getResult().getHReturn(), new DataWord(i).getData()); + } + + // deploy contract again + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), + factoryAddress, Hex.decode(hexInput), 0, fee, manager, null); + Assert.assertNotNull(result.getRuntime().getRuntimeError()); + Assert.assertEquals(result.getRuntime().getRuntimeError(), "REVERT opcode executed"); + + } + +} diff --git a/src/test/java/org/tron/common/runtime/vm/CreateContractSuicideTest.java b/src/test/java/org/tron/common/runtime/vm/CreateContractSuicideTest.java index bde281904da..4f8592ac375 100644 --- a/src/test/java/org/tron/common/runtime/vm/CreateContractSuicideTest.java +++ b/src/test/java/org/tron/common/runtime/vm/CreateContractSuicideTest.java @@ -7,7 +7,7 @@ import org.spongycastle.util.encoders.Hex; import org.testng.Assert; import org.tron.common.runtime.Runtime; -import org.tron.common.runtime.TVMTestUtils; +import org.tron.common.runtime.TvmTestUtils; import org.tron.common.runtime.config.VMConfig; import org.tron.common.runtime.vm.program.Program.OutOfEnergyException; import org.tron.common.storage.DepositImpl; @@ -118,27 +118,27 @@ public void testAAfterAllowMultiSignProposal() .statsByVersion(ForkBlockVersionEnum.VERSION_3_5.getValue(), stats); VMConfig.initAllowMultiSign(1); - Transaction aTrx = TVMTestUtils.generateDeploySmartContractAndGetTransaction( + Transaction aTrx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( "testA", address, abi, aCode, value, fee, consumeUserResourcePercent, null, engeryLimit); - Runtime aRuntime = TVMTestUtils + Runtime aRuntime = TvmTestUtils .processTransactionAndReturnRuntime(aTrx, DepositImpl.createRoot(manager), null); Assert.assertEquals(aRuntime.getRuntimeError(), "REVERT opcode executed"); - Transaction bTrx = TVMTestUtils.generateDeploySmartContractAndGetTransaction( + Transaction bTrx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( "testB", address, abi, bCode, value, fee, consumeUserResourcePercent, null, engeryLimit); - Runtime bRuntime = TVMTestUtils + Runtime bRuntime = TvmTestUtils .processTransactionAndReturnRuntime(bTrx, DepositImpl.createRoot(manager), null); Assert.assertEquals(bRuntime.getRuntimeError(), "REVERT opcode executed"); - Transaction cTrx = TVMTestUtils.generateDeploySmartContractAndGetTransaction( + Transaction cTrx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( "testC", address, abi, cCode, value, fee, consumeUserResourcePercent, null, engeryLimit); - Runtime cRuntime = TVMTestUtils + Runtime cRuntime = TvmTestUtils .processTransactionAndReturnRuntime(cTrx, DepositImpl.createRoot(manager), null); Assert.assertTrue(cRuntime.getResult().getException() instanceof OutOfEnergyException); - Transaction dTrx = TVMTestUtils.generateDeploySmartContractAndGetTransaction( + Transaction dTrx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( "testC", address, abi, dCode, value, fee, consumeUserResourcePercent, null, engeryLimit); - Runtime dRuntime = TVMTestUtils + Runtime dRuntime = TvmTestUtils .processTransactionAndReturnRuntime(dTrx, DepositImpl.createRoot(manager), null); Assert.assertEquals(dRuntime.getRuntimeError(), "REVERT opcode executed"); @@ -149,28 +149,28 @@ public void testABeforeAllowMultiSignProposal() throws ContractExeException, ReceiptCheckErrException, VMIllegalException, ContractValidateException { VMConfig.initAllowMultiSign(0); byte[] address = Hex.decode(OWNER_ADDRESS); - Transaction aTrx = TVMTestUtils.generateDeploySmartContractAndGetTransaction( + Transaction aTrx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( "testA", address, abi, aCode, value, fee, consumeUserResourcePercent, null, engeryLimit); - Runtime aRuntime = TVMTestUtils + Runtime aRuntime = TvmTestUtils .processTransactionAndReturnRuntime(aTrx, DepositImpl.createRoot(manager), null); Assert.assertEquals(aRuntime.getRuntimeError(), "Unknown Exception"); // // - Transaction bTrx = TVMTestUtils.generateDeploySmartContractAndGetTransaction( + Transaction bTrx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( "testB", address, abi, bCode, value, fee, consumeUserResourcePercent, null, engeryLimit); - Runtime bRuntime = TVMTestUtils + Runtime bRuntime = TvmTestUtils .processTransactionAndReturnRuntime(bTrx, DepositImpl.createRoot(manager), null); Assert.assertEquals(bRuntime.getRuntimeError(), "REVERT opcode executed"); - Transaction cTrx = TVMTestUtils.generateDeploySmartContractAndGetTransaction( + Transaction cTrx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( "testC", address, abi, cCode, value, fee, consumeUserResourcePercent, null, engeryLimit); - Runtime cRuntime = TVMTestUtils + Runtime cRuntime = TvmTestUtils .processTransactionAndReturnRuntime(cTrx, DepositImpl.createRoot(manager), null); Assert.assertTrue(cRuntime.getResult().getException() instanceof OutOfEnergyException); - Transaction dTrx = TVMTestUtils.generateDeploySmartContractAndGetTransaction( + Transaction dTrx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( "testC", address, abi, dCode, value, fee, consumeUserResourcePercent, null, engeryLimit); - Runtime dRuntime = TVMTestUtils + Runtime dRuntime = TvmTestUtils .processTransactionAndReturnRuntime(dTrx, DepositImpl.createRoot(manager), null); Assert.assertEquals(dRuntime.getRuntimeError(), "REVERT opcode executed"); diff --git a/src/test/java/org/tron/common/runtime/vm/DataWordTest.java b/src/test/java/org/tron/common/runtime/vm/DataWordTest.java index a3192ea18e0..2a2dd14facd 100644 --- a/src/test/java/org/tron/common/runtime/vm/DataWordTest.java +++ b/src/test/java/org/tron/common/runtime/vm/DataWordTest.java @@ -21,6 +21,7 @@ import static org.junit.Assert.assertTrue; import java.math.BigInteger; +import java.util.Arrays; import lombok.extern.slf4j.Slf4j; import org.junit.Test; import org.spongycastle.util.encoders.Hex; @@ -451,4 +452,139 @@ private static BigInteger pow(BigInteger x, BigInteger y) { } return result; } + + @Test + public void testShiftLeft() { + Object[][] cases = { + {"0000000000000000000000000000000000000000000000000000000000000001", "00", + "0000000000000000000000000000000000000000000000000000000000000001"}, + {"0000000000000000000000000000000000000000000000000000000000000001", "01", + "0000000000000000000000000000000000000000000000000000000000000002"}, + {"0000000000000000000000000000000000000000000000000000000000000001", "ff", + "8000000000000000000000000000000000000000000000000000000000000000"}, + {"0000000000000000000000000000000000000000000000000000000000000001", "0100", + "0000000000000000000000000000000000000000000000000000000000000000"}, + {"0000000000000000000000000000000000000000000000000000000000000001", "0101", + "0000000000000000000000000000000000000000000000000000000000000000"}, + {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "00", + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "01", + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"}, + {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ff", + "8000000000000000000000000000000000000000000000000000000000000000"}, + {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0100", + "0000000000000000000000000000000000000000000000000000000000000000"}, + {"0000000000000000000000000000000000000000000000000000000000000000", "01", + "0000000000000000000000000000000000000000000000000000000000000000"}, + {"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "01", + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"}, + }; + + testShiftLeft(cases); + } + + private void testShiftLeft(Object[][] cases) { + for (Object[] c : cases) { + DataWord value = new DataWord(Hex.decode(c[0].toString())); + DataWord arg = new DataWord(Hex.decode(c[1].toString())); + DataWord expected = new DataWord(Hex.decode(c[2].toString())); + DataWord result = value.shiftLeft(arg); + + assertEquals(result, expected); + } + } + + @Test + public void testShiftRight() { + Object[][] cases = { + {"0000000000000000000000000000000000000000000000000000000000000001", "00", + "0000000000000000000000000000000000000000000000000000000000000001"}, + {"0000000000000000000000000000000000000000000000000000000000000001", "01", + "0000000000000000000000000000000000000000000000000000000000000000"}, + {"8000000000000000000000000000000000000000000000000000000000000000", "01", + "4000000000000000000000000000000000000000000000000000000000000000"}, + {"8000000000000000000000000000000000000000000000000000000000000000", "ff", + "0000000000000000000000000000000000000000000000000000000000000001"}, + {"8000000000000000000000000000000000000000000000000000000000000000", "0100", + "0000000000000000000000000000000000000000000000000000000000000000"}, + {"8000000000000000000000000000000000000000000000000000000000000000", "0101", + "0000000000000000000000000000000000000000000000000000000000000000"}, + {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "00", + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "01", + "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ff", + "0000000000000000000000000000000000000000000000000000000000000001"}, + {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0100", + "0000000000000000000000000000000000000000000000000000000000000000"}, + {"0000000000000000000000000000000000000000000000000000000000000000", "01", + "0000000000000000000000000000000000000000000000000000000000000000"}, + }; + + testShiftRight(cases); + } + + private void testShiftRight(Object[][] cases) { + for (Object[] c : cases) { + DataWord value = new DataWord(c[0].toString()); + DataWord arg = new DataWord(c[1].toString()); + DataWord expected = new DataWord(c[2].toString()); + DataWord result = value.shiftRight(arg); + + assertEquals(result, expected); + } + } + + @Test + public void testShiftRightSigned() { + String[][] cases = { + {"0000000000000000000000000000000000000000000000000000000000000001", "00", + "0000000000000000000000000000000000000000000000000000000000000001"}, + {"0000000000000000000000000000000000000000000000000000000000000001", "01", + "0000000000000000000000000000000000000000000000000000000000000000"}, + {"8000000000000000000000000000000000000000000000000000000000000000", "01", + "c000000000000000000000000000000000000000000000000000000000000000"}, + {"8000000000000000000000000000000000000000000000000000000000000000", "ff", + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"8000000000000000000000000000000000000000000000000000000000000000", "0100", + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"8000000000000000000000000000000000000000000000000000000000000000", "0101", + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "00", + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "01", + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ff", + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0100", + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"0000000000000000000000000000000000000000000000000000000000000000", "01", + "0000000000000000000000000000000000000000000000000000000000000000"}, + {"4000000000000000000000000000000000000000000000000000000000000000", "fe", + "0000000000000000000000000000000000000000000000000000000000000001"}, + {"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "f8", + "000000000000000000000000000000000000000000000000000000000000007f"}, + {"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "fe", + "0000000000000000000000000000000000000000000000000000000000000001"}, + {"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ff", + "0000000000000000000000000000000000000000000000000000000000000000"}, + {"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0100", + "0000000000000000000000000000000000000000000000000000000000000000"}, + }; + + testShiftRightSigned(cases); + } + + private void testShiftRightSigned(String[][] cases) { + int i = 1; + for (String[] c : cases) { + DataWord value = new DataWord(c[0]); + DataWord arg = new DataWord(c[1]); + DataWord expected = new DataWord(c[2]); + DataWord actual = value.shiftRightSigned(arg); + assertEquals(i + " " + Arrays.asList(c).toString(), expected, actual); + } + } + + } diff --git a/src/test/java/org/tron/common/runtime/vm/DepositTest.java b/src/test/java/org/tron/common/runtime/vm/DepositTest.java index 467b1ab6933..a432e2242d0 100644 --- a/src/test/java/org/tron/common/runtime/vm/DepositTest.java +++ b/src/test/java/org/tron/common/runtime/vm/DepositTest.java @@ -13,7 +13,7 @@ import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.Runtime; import org.tron.common.runtime.TVMTestResult; -import org.tron.common.runtime.TVMTestUtils; +import org.tron.common.runtime.TvmTestUtils; import org.tron.common.runtime.config.VMConfig; import org.tron.common.storage.Deposit; import org.tron.common.storage.DepositImpl; @@ -118,15 +118,15 @@ public void loopCallTest() long consumeUserResourcePercent = 0; long engeryLiimt = 100000000; - Transaction aTrx = TVMTestUtils.generateDeploySmartContractAndGetTransaction( + Transaction aTrx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( contractA, address, aABI, aCode, value, fee, consumeUserResourcePercent, null, engeryLiimt); - Runtime runtime = TVMTestUtils + Runtime runtime = TvmTestUtils .processTransactionAndReturnRuntime(aTrx, DepositImpl.createRoot(manager), null); Assert.assertNull(runtime.getRuntimeError()); - Transaction bTrx = TVMTestUtils.generateDeploySmartContractAndGetTransaction( + Transaction bTrx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( contractB, address, bABI, bCode, value, fee, consumeUserResourcePercent, null, engeryLiimt); - runtime = TVMTestUtils + runtime = TvmTestUtils .processTransactionAndReturnRuntime(bTrx, DepositImpl.createRoot(manager), null); Assert.assertNull(runtime.getRuntimeError()); @@ -141,23 +141,23 @@ public void loopCallTest() + "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"; System.err.println(params1); - byte[] triggerData = TVMTestUtils - .parseABI("callBcallARevert(address,uint256,uint256)", params1); - TVMTestResult result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + byte[] triggerData = TvmTestUtils + .parseAbi("callBcallARevert(address,uint256,uint256)", params1); + TVMTestResult result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), aAddress, triggerData, 0, fee, manager, null); Assert.assertNull(result.getRuntime().getRuntimeError()); // check result // expected: n1 = 1; n2 = 0 - byte[] checkN1Data = TVMTestUtils.parseABI("n1()", null); - byte[] checkN2Data = TVMTestUtils.parseABI("n2()", null); + byte[] checkN1Data = TvmTestUtils.parseAbi("n1()", null); + byte[] checkN2Data = TvmTestUtils.parseAbi("n2()", null); - TVMTestResult checkN1 = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + TVMTestResult checkN1 = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), aAddress, checkN1Data, 0, fee, manager, null); - TVMTestResult checkN2 = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + TVMTestResult checkN2 = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), aAddress, checkN2Data, 0, fee, manager, null); System.out.println(Hex.toHexString(checkN1.getRuntime().getResult().getHReturn())); @@ -171,16 +171,16 @@ public void loopCallTest() // ,100,1000 String params2 = Hex.toHexString(new DataWord(bAddress).getData()) + "000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000003e8"; - triggerData = TVMTestUtils.parseABI("callBcallA(address,uint256,uint256)", params2); - result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + triggerData = TvmTestUtils.parseAbi("callBcallA(address,uint256,uint256)", params2); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), aAddress, triggerData, 0, fee, manager, null); Assert.assertNull(result.getRuntime().getRuntimeError()); - checkN1 = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + checkN1 = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), aAddress, checkN1Data, 0, fee, manager, null); - checkN2 = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + checkN2 = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), aAddress, checkN2Data, 0, fee, manager, null); System.out.println(Hex.toHexString(checkN1.getRuntime().getResult().getHReturn())); System.out.println(Hex.toHexString(checkN2.getRuntime().getResult().getHReturn())); @@ -212,16 +212,16 @@ public void loopCallTestOldVersion() long fee = 100000000; long consumeUserResourcePercent = 0; - Transaction aTrx = TVMTestUtils.generateDeploySmartContractAndGetTransaction( + Transaction aTrx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( contractA, address, aABI, aCode, value, fee, consumeUserResourcePercent, null); Deposit rootDeposit = DepositImpl.createRoot(manager); - Runtime runtime = TVMTestUtils.processTransactionAndReturnRuntime(aTrx, rootDeposit, null); + Runtime runtime = TvmTestUtils.processTransactionAndReturnRuntime(aTrx, rootDeposit, null); Assert.assertNull(runtime.getRuntimeError()); - Transaction bTrx = TVMTestUtils.generateDeploySmartContractAndGetTransaction( + Transaction bTrx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( contractB, address, bABI, bCode, value, fee, consumeUserResourcePercent, null); rootDeposit = DepositImpl.createRoot(manager); - runtime = TVMTestUtils.processTransactionAndReturnRuntime(bTrx, rootDeposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(bTrx, rootDeposit, null); Assert.assertNull(runtime.getRuntimeError()); byte[] aAddress = Wallet.generateContractAddress(aTrx); @@ -234,23 +234,23 @@ public void loopCallTestOldVersion() String params1 = Hex.toHexString(new DataWord(bAddress).getData()) + "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"; - byte[] triggerData = TVMTestUtils - .parseABI("callBcallARevert(address,uint256,uint256)", params1); - TVMTestResult result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + byte[] triggerData = TvmTestUtils + .parseAbi("callBcallARevert(address,uint256,uint256)", params1); + TVMTestResult result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), aAddress, triggerData, 0, fee, manager, null); Assert.assertNull(result.getRuntime().getRuntimeError()); // check result // expected: n1 = 1; n2 = 0 - byte[] checkN1Data = TVMTestUtils.parseABI("n1()", null); - byte[] checkN2Data = TVMTestUtils.parseABI("n2()", null); + byte[] checkN1Data = TvmTestUtils.parseAbi("n1()", null); + byte[] checkN2Data = TvmTestUtils.parseAbi("n2()", null); - TVMTestResult checkN1 = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + TVMTestResult checkN1 = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), aAddress, checkN1Data, 0, fee, manager, null); - TVMTestResult checkN2 = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + TVMTestResult checkN2 = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), aAddress, checkN2Data, 0, fee, manager, null); System.out.println(Hex.toHexString(checkN1.getRuntime().getResult().getHReturn())); @@ -264,16 +264,16 @@ public void loopCallTestOldVersion() // ,100,1000 String params2 = Hex.toHexString(new DataWord(bAddress).getData()) + "000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000003e8"; - triggerData = TVMTestUtils.parseABI("callBcallA(address,uint256,uint256)", params2); - result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + triggerData = TvmTestUtils.parseAbi("callBcallA(address,uint256,uint256)", params2); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), aAddress, triggerData, 0, fee, manager, null); Assert.assertNull(result.getRuntime().getRuntimeError()); - checkN1 = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + checkN1 = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), aAddress, checkN1Data, 0, fee, manager, null); - checkN2 = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + checkN2 = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), aAddress, checkN2Data, 0, fee, manager, null); System.out.println(Hex.toHexString(checkN1.getRuntime().getResult().getHReturn())); System.out.println(Hex.toHexString(checkN2.getRuntime().getResult().getHReturn())); diff --git a/src/test/java/org/tron/common/runtime/vm/EnergyWhenAssertStyleTest.java b/src/test/java/org/tron/common/runtime/vm/EnergyWhenAssertStyleTest.java index 9734223252f..81ffdaae3cb 100644 --- a/src/test/java/org/tron/common/runtime/vm/EnergyWhenAssertStyleTest.java +++ b/src/test/java/org/tron/common/runtime/vm/EnergyWhenAssertStyleTest.java @@ -12,7 +12,7 @@ import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.TVMTestResult; -import org.tron.common.runtime.TVMTestUtils; +import org.tron.common.runtime.TvmTestUtils; import org.tron.common.runtime.vm.program.Program.IllegalOperationException; import org.tron.common.runtime.vm.program.Program.OutOfMemoryException; import org.tron.common.runtime.vm.program.Program.PrecompiledContractException; @@ -97,8 +97,8 @@ public void outOfIndexTest() String code = "608060405234801561001057600080fd5b5060c58061001f6000396000f300608060405260043610603e5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416639a4e1fa081146043575b600080fd5b348015604e57600080fd5b5060556057565b005b60408051600a80825261016082019092526060916020820161014080388339019050509050600a81600a815181101515608c57fe5b60209081029091010152505600a165627a7a723058201aaf6626083e32afa834a13d3365784c509d10f57ce1024f88c697cf0718795e0029"; String libraryAddressPair = null; - TVMTestResult result = TVMTestUtils - .deployContractAndReturnTVMTestResult(contractName, address, ABI, code, + TVMTestResult result = TvmTestUtils + .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair, dbManager, null); @@ -109,9 +109,9 @@ public void outOfIndexTest() totalBalance - expectEnergyUsageTotal * 100); byte[] contractAddress = result.getContractAddress(); - byte[] triggerData = TVMTestUtils.parseABI("testOutOfIndex()", null); - result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + byte[] triggerData = TvmTestUtils.parseAbi("testOutOfIndex()", null); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, 0, feeLimit, dbManager, null); long expectEnergyUsageTotal2 = feeLimit / 100; @@ -148,8 +148,8 @@ public void bytesNTest() String code = "6080604052348015600f57600080fd5b50609f8061001e6000396000f300608060405260043610603e5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631e76e10781146043575b600080fd5b348015604e57600080fd5b5060556057565b005b7201234500000000000000000000000000000000601460008282fe00a165627a7a72305820a1c7c81d642cc0aa11c43d63614a5b3c018e4af84700af4bfde5f2efb18b55130029"; String libraryAddressPair = null; - TVMTestResult result = TVMTestUtils - .deployContractAndReturnTVMTestResult(contractName, address, ABI, code, + TVMTestResult result = TvmTestUtils + .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair, dbManager, null); @@ -160,9 +160,9 @@ public void bytesNTest() totalBalance - expectEnergyUsageTotal * 100); byte[] contractAddress = result.getContractAddress(); - byte[] triggerData = TVMTestUtils.parseABI("testbytesN()", null); - result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + byte[] triggerData = TvmTestUtils.parseAbi("testbytesN()", null); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, 0, feeLimit, dbManager, null); long expectEnergyUsageTotal2 = feeLimit / 100; @@ -198,8 +198,8 @@ public void divZeroTest() String code = "6080604052348015600f57600080fd5b50608b8061001e6000396000f300608060405260043610603e5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663b87d948d81146043575b600080fd5b348015604e57600080fd5b5060556057565b005b60008080600afe00a165627a7a7230582084ed35f2e244d6721bb5f5fcaf53d237ea050b3de84d5cc7fee74584fd2ff31f0029"; String libraryAddressPair = null; - TVMTestResult result = TVMTestUtils - .deployContractAndReturnTVMTestResult(contractName, address, ABI, code, + TVMTestResult result = TvmTestUtils + .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair, dbManager, null); @@ -210,9 +210,9 @@ public void divZeroTest() totalBalance - expectEnergyUsageTotal * 100); byte[] contractAddress = result.getContractAddress(); - byte[] triggerData = TVMTestUtils.parseABI("testDivZero()", null); - result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + byte[] triggerData = TvmTestUtils.parseAbi("testDivZero()", null); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, 0, feeLimit, dbManager, null); long expectEnergyUsageTotal2 = feeLimit / 100; @@ -249,8 +249,8 @@ public void shiftByNegativeTest() String code = "6080604052348015600f57600080fd5b50608e8061001e6000396000f300608060405260043610603e5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663e88e362a81146043575b600080fd5b348015604e57600080fd5b5060556057565b005b600919600081610400fe00a165627a7a7230582086c99cfe65e26909bb0fb3a2bdaf2385ad8dfff72680adab954063a4fe1d549b0029"; String libraryAddressPair = null; - TVMTestResult result = TVMTestUtils - .deployContractAndReturnTVMTestResult(contractName, address, ABI, code, + TVMTestResult result = TvmTestUtils + .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair, dbManager, null); @@ -261,9 +261,9 @@ public void shiftByNegativeTest() totalBalance - expectEnergyUsageTotal * 100); byte[] contractAddress = result.getContractAddress(); - byte[] triggerData = TVMTestUtils.parseABI("testShiftByNegative()", null); - result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + byte[] triggerData = TvmTestUtils.parseAbi("testShiftByNegative()", null); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, 0, feeLimit, dbManager, null); long expectEnergyUsageTotal2 = feeLimit / 100; @@ -301,8 +301,8 @@ public void enumTypeTest() String code = "6080604052348015600f57600080fd5b5060898061001e6000396000f300608060405260043610603e5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416635a43cddc81146043575b600080fd5b348015604e57600080fd5b5060556057565b005b6000600afe00a165627a7a72305820b24a4d459b753723d300f56c408c6120d5ef0c7ddb166d66ccf4277a76ad83ed0029"; String libraryAddressPair = null; - TVMTestResult result = TVMTestUtils - .deployContractAndReturnTVMTestResult(contractName, address, ABI, code, + TVMTestResult result = TvmTestUtils + .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair, dbManager, null); @@ -313,9 +313,9 @@ public void enumTypeTest() totalBalance - expectEnergyUsageTotal * 100); byte[] contractAddress = result.getContractAddress(); - byte[] triggerData = TVMTestUtils.parseABI("testEnumType()", null); - result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + byte[] triggerData = TvmTestUtils.parseAbi("testEnumType()", null); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, 0, feeLimit, dbManager, null); long expectEnergyUsageTotal2 = feeLimit / 100; @@ -351,8 +351,8 @@ public void functionPointerTest() String code = "6080604052348015600f57600080fd5b5060988061001e6000396000f300608060405260043610603e5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663e9ad8ee781146043575b600080fd5b348015604e57600080fd5b5060556057565b005b606a606660018263ffffffff16565b5050565bfe00a165627a7a723058201c8982fa288ec7aad86b1d1992ecc5d08c4b22e4fe037981f91aff8bcbd900680029"; String libraryAddressPair = null; - TVMTestResult result = TVMTestUtils - .deployContractAndReturnTVMTestResult(contractName, address, ABI, code, + TVMTestResult result = TvmTestUtils + .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair, dbManager, null); @@ -363,9 +363,9 @@ public void functionPointerTest() totalBalance - expectEnergyUsageTotal * 100); byte[] contractAddress = result.getContractAddress(); - byte[] triggerData = TVMTestUtils.parseABI("testFunctionPointer()", null); - result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + byte[] triggerData = TvmTestUtils.parseAbi("testFunctionPointer()", null); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, 0, feeLimit, dbManager, null); long expectEnergyUsageTotal2 = feeLimit / 100; @@ -401,8 +401,8 @@ public void assertTest() String code = "6080604052348015600f57600080fd5b5060858061001e6000396000f300608060405260043610603e5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416632b813bc081146043575b600080fd5b348015604e57600080fd5b5060556057565b005bfe00a165627a7a723058208ce7511bd3a946a22baaba2b4521cbf29d2481ad52887c5567e422cd89726eda0029"; String libraryAddressPair = null; - TVMTestResult result = TVMTestUtils - .deployContractAndReturnTVMTestResult(contractName, address, ABI, code, + TVMTestResult result = TvmTestUtils + .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair, dbManager, null); @@ -413,9 +413,9 @@ public void assertTest() totalBalance - expectEnergyUsageTotal * 100); byte[] contractAddress = result.getContractAddress(); - byte[] triggerData = TVMTestUtils.parseABI("testAssert()", null); - result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + byte[] triggerData = TvmTestUtils.parseAbi("testAssert()", null); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, 0, feeLimit, dbManager, null); long expectEnergyUsageTotal2 = feeLimit / 100; @@ -456,8 +456,8 @@ public void systemPrecompileTest() String code = "608060405260008054600160a060020a0319166201000117905534801561002557600080fd5b50610159806100356000396000f30060806040526004361061004b5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663906fbec98114610050578063cee14bb41461008e575b600080fd5b34801561005c57600080fd5b506100656100c1565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b34801561009a57600080fd5b506100bf73ffffffffffffffffffffffffffffffffffffffff600435166024356100dd565b005b60005473ffffffffffffffffffffffffffffffffffffffff1681565b600080546040805173ffffffffffffffffffffffffffffffffffffffff868116825260208201869052825193169381830193909290918290030181855af4915050151561012957600080fd5b50505600a165627a7a723058206090aa7a8ac0e45fac642652417495e81dad6f1592343bff8cfe97f61cf74e880029"; String libraryAddressPair = null; - TVMTestResult result = TVMTestUtils - .deployContractAndReturnTVMTestResult(contractName, address, ABI, code, + TVMTestResult result = TvmTestUtils + .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair, dbManager, null); @@ -472,9 +472,9 @@ public void systemPrecompileTest() Hex.toHexString(new DataWord(new DataWord(contractAddress).getLast20Bytes()).getData()) + "0000000000000000000000000000000000000000000000000000000000000003"; - byte[] triggerData = TVMTestUtils.parseABI("voteForSingleWitness(address,uint256)", params); - result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + byte[] triggerData = TvmTestUtils.parseAbi("voteForSingleWitness(address,uint256)", params); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, 0, feeLimit, dbManager, null); long expectEnergyUsageTotal2 = feeLimit / 100; @@ -510,8 +510,8 @@ public void outOfMemTest() String code = "608060405234801561001057600080fd5b5060ca8061001f6000396000f300608060405260043610603e5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663e31fcf3c81146043575b600080fd5b348015604e57600080fd5b506058600435605a565b005b600060605b828210156099576040805162300400808252630600802082019092529060208201630600800080388339019050506001909201919050605f565b5050505600a165627a7a723058209e5d294a7bf5133b304bc6851c749cd5e1f4748230405755e6bd2e31549ae1d00029"; String libraryAddressPair = null; - TVMTestResult result = TVMTestUtils - .deployContractAndReturnTVMTestResult(contractName, address, ABI, code, + TVMTestResult result = TvmTestUtils + .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair, dbManager, null); @@ -522,9 +522,9 @@ public void outOfMemTest() totalBalance - expectEnergyUsageTotal * 100); byte[] contractAddress = result.getContractAddress(); String params = "0000000000000000000000000000000000000000000000000000000000000001"; - byte[] triggerData = TVMTestUtils.parseABI("testMem(uint256)", params); - result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + byte[] triggerData = TvmTestUtils.parseAbi("testMem(uint256)", params); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, 0, feeLimit, dbManager, null); long expectEnergyUsageTotal2 = feeLimit / 100; diff --git a/src/test/java/org/tron/common/runtime/vm/EnergyWhenRequireStyleTest.java b/src/test/java/org/tron/common/runtime/vm/EnergyWhenRequireStyleTest.java index 8c0589bc323..05190a59940 100644 --- a/src/test/java/org/tron/common/runtime/vm/EnergyWhenRequireStyleTest.java +++ b/src/test/java/org/tron/common/runtime/vm/EnergyWhenRequireStyleTest.java @@ -12,7 +12,7 @@ import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.TVMTestResult; -import org.tron.common.runtime.TVMTestUtils; +import org.tron.common.runtime.TvmTestUtils; import org.tron.common.runtime.vm.program.Program.OutOfEnergyException; import org.tron.common.storage.DepositImpl; import org.tron.common.utils.FileUtil; @@ -91,8 +91,8 @@ public void throwTest() String code = "6080604052348015600f57600080fd5b5060838061001e6000396000f300608060405260043610603e5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166350bff6bf81146043575b600080fd5b348015604e57600080fd5b506055603e565b0000a165627a7a72305820f51282c5910e3ff1b5f2e9509f3cf23c7035027aae1947ab46e5a9252fb061eb0029"; String libraryAddressPair = null; - TVMTestResult result = TVMTestUtils - .deployContractAndReturnTVMTestResult(contractName, address, ABI, code, + TVMTestResult result = TvmTestUtils + .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair, dbManager, null); @@ -104,9 +104,9 @@ public void throwTest() byte[] contractAddress = result.getContractAddress(); /* ====================================================================== */ - byte[] triggerData = TVMTestUtils.parseABI("testThrow()", null); - result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + byte[] triggerData = TvmTestUtils.parseAbi("testThrow()", null); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, 0, feeLimit, dbManager, null); long expectEnergyUsageTotal2 = 124; @@ -142,8 +142,8 @@ public void requireTest() String code = "6080604052348015600f57600080fd5b5060838061001e6000396000f300608060405260043610603e5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663357815c481146043575b600080fd5b348015604e57600080fd5b506055603e565b0000a165627a7a7230582054141931bcc37d4f266815f02d2fb113f5af20825cbce45d3b0f2fe90ac0145d0029"; String libraryAddressPair = null; - TVMTestResult result = TVMTestUtils - .deployContractAndReturnTVMTestResult(contractName, address, ABI, code, + TVMTestResult result = TvmTestUtils + .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair, dbManager, null); @@ -155,9 +155,9 @@ public void requireTest() byte[] contractAddress = result.getContractAddress(); /* ====================================================================== */ - byte[] triggerData = TVMTestUtils.parseABI("testRequire()", null); - result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + byte[] triggerData = TvmTestUtils.parseAbi("testRequire()", null); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, 0, feeLimit, dbManager, null); long expectEnergyUsageTotal2 = 124; @@ -198,8 +198,8 @@ public void thisFunctionViaMessageCallTest() String code = "608060405234801561001057600080fd5b50610121806100206000396000f30060806040526004361060485763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416632b813bc08114604d5780635df83fe7146061575b600080fd5b348015605857600080fd5b50605f6073565b005b348015606c57600080fd5b50605f6075565bfe5b3073ffffffffffffffffffffffffffffffffffffffff16632b813bc06113886040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401600060405180830381600088803b15801560db57600080fd5b5087f115801560ee573d6000803e3d6000fd5b50505050505600a165627a7a7230582087d830c44fb566498789b212e3d0374f7a7589a2efdda11b3a4c03051b57891a0029"; String libraryAddressPair = null; - TVMTestResult result = TVMTestUtils - .deployContractAndReturnTVMTestResult(contractName, address, ABI, code, + TVMTestResult result = TvmTestUtils + .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair, dbManager, null); @@ -211,9 +211,9 @@ public void thisFunctionViaMessageCallTest() byte[] contractAddress = result.getContractAddress(); /* ====================================================================== */ - byte[] triggerData = TVMTestUtils.parseABI("testThisFunctionViaMessageCall()", null); - result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + byte[] triggerData = TvmTestUtils.parseAbi("testThisFunctionViaMessageCall()", null); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, 0, feeLimit, dbManager, null); long expectEnergyUsageTotal2 = 5339; @@ -263,8 +263,8 @@ public void thatFunctionViaMessageCallTest() String code = "608060405234801561001057600080fd5b506101e6806100206000396000f3006080604052600436106100405763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416637dbc1cb88114610045575b600080fd5b34801561005157600080fd5b5061005a61005c565b005b6000610066610108565b604051809103906000f080158015610082573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff16632b813bc06113886040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401600060405180830381600088803b1580156100ec57600080fd5b5087f1158015610100573d6000803e3d6000fd5b505050505050565b60405160a3806101188339019056006080604052348015600f57600080fd5b5060858061001e6000396000f300608060405260043610603e5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416632b813bc081146043575b600080fd5b348015604e57600080fd5b5060556057565b005bfe00a165627a7a72305820c02c76575c2a0ada80c3f6db47f885cece6c254d1e7c79eb6ddc1c1d4e70ebae0029a165627a7a72305820cf879e62f738b44636adf61bd4b2fb38c10f027d2a4484d58baf44a06dc97bd90029"; String libraryAddressPair = null; - TVMTestResult result = TVMTestUtils - .deployContractAndReturnTVMTestResult(contractName, address, ABI, code, + TVMTestResult result = TvmTestUtils + .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair, dbManager, null); @@ -276,9 +276,9 @@ public void thatFunctionViaMessageCallTest() byte[] contractAddress = result.getContractAddress(); /* ====================================================================== */ - byte[] triggerData = TVMTestUtils.parseABI("testThatFunctionViaMessageCall()", null); - result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + byte[] triggerData = TvmTestUtils.parseAbi("testThatFunctionViaMessageCall()", null); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, 0, feeLimit, dbManager, null); long expectEnergyUsageTotal2 = 64125; @@ -321,8 +321,8 @@ public void newContractTest1() String code = "608060405234801561001057600080fd5b5060d58061001f6000396000f3006080604052600436106100405763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416635d10a9e68114610045575b600080fd5b34801561005157600080fd5b5061005a61005c565b005b6000610066610087565b604051809103906000f080158015610082573d6000803e3d6000fd5b505050565b6040516013806100978339019056006080604052348015600f57600080fd5b50fe00a165627a7a72305820685ff8f74890f671deb4d3881a4b72ab0daac2ab0d36112e1ebdf98a43ac4d940029"; String libraryAddressPair = null; - TVMTestResult result = TVMTestUtils - .deployContractAndReturnTVMTestResult(contractName, address, ABI, code, + TVMTestResult result = TvmTestUtils + .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair, dbManager, null); @@ -334,9 +334,9 @@ public void newContractTest1() byte[] contractAddress = result.getContractAddress(); /* ====================================================================== */ - byte[] triggerData = TVMTestUtils.parseABI("testNewContract()", null); - result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + byte[] triggerData = TvmTestUtils.parseAbi("testNewContract()", null); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, 0, feeLimit, dbManager, null); long expectEnergyUsageTotal2 = feeLimit / 100; @@ -385,8 +385,8 @@ public void receiveTrxWithoutPayableTest() String code = "608060405234801561001057600080fd5b506101f5806100206000396000f3006080604052600436106100405763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416638a46bf6d8114610045575b600080fd5b61004d61004f565b005b600061005961015f565b604051809103906000f080158015610075573d6000803e3d6000fd5b5060408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f60f59d44000000000000000000000000000000000000000000000000000000001781529151815193945073ffffffffffffffffffffffffffffffffffffffff851693600193829180838360005b8381101561010e5781810151838201526020016100f6565b50505050905090810190601f16801561013b5780820380516001836020036101000a031916815260200191505b5091505060006040518083038185875af11515925061015c91505057600080fd5b50565b604051605b8061016f8339019056006080604052348015600f57600080fd5b50603e80601d6000396000f3006080604052348015600f57600080fd5b500000a165627a7a72305820a82006ee5ac783bcea7085501eaed33360b3120278f1f39e611afedc9f4a693b0029a165627a7a72305820a50d9536f182fb6aefc737fdc3a675630e75a08de88deb6b1bee6d4b6dff04730029"; String libraryAddressPair = null; - TVMTestResult result = TVMTestUtils - .deployContractAndReturnTVMTestResult(contractName, address, ABI, code, + TVMTestResult result = TvmTestUtils + .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair, dbManager, null); @@ -399,8 +399,8 @@ public void receiveTrxWithoutPayableTest() Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), totalBalance - expectEnergyUsageTotal * 100); - result = TVMTestUtils - .deployContractAndReturnTVMTestResult(contractName, address, ABI, code, + result = TvmTestUtils + .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, 0, feeLimit, consumeUserResourcePercent, libraryAddressPair, dbManager, null); @@ -410,9 +410,9 @@ public void receiveTrxWithoutPayableTest() Assert.assertEquals(dbManager.getAccountStore().get(address).getBalance(), totalBalance - (expectEnergyUsageTotal + expectEnergyUsageTotal2) * 100); /* ====================================================================== */ - byte[] triggerData = TVMTestUtils.parseABI("testFallback()", null); - result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + byte[] triggerData = TvmTestUtils.parseAbi("testFallback()", null); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, 10, feeLimit, dbManager, null); long expectEnergyUsageTotal3 = 51833; @@ -462,8 +462,8 @@ public void revertTest() String code = "608060405234801561001057600080fd5b5060b68061001f6000396000f30060806040526004361060485763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166312065fe08114604d578063a26388bb146071575b600080fd5b348015605857600080fd5b50605f6085565b60408051918252519081900360200190f35b348015607c57600080fd5b5060836048565b005b3031905600a165627a7a7230582059cab3a7a5851a7852c728ec8729456a04dc022674976f3f26bfd51491dbf1080029"; String libraryAddressPair = null; - TVMTestResult result = TVMTestUtils - .deployContractAndReturnTVMTestResult(contractName, address, ABI, code, + TVMTestResult result = TvmTestUtils + .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair, dbManager, null); @@ -475,9 +475,9 @@ public void revertTest() byte[] contractAddress = result.getContractAddress(); /* ====================================================================== */ - byte[] triggerData = TVMTestUtils.parseABI("testRevert()", null); - result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + byte[] triggerData = TvmTestUtils.parseAbi("testRevert()", null); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, 0, feeLimit, dbManager, null); long expectEnergyUsageTotal2 = 146; diff --git a/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java b/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java index 99c4f7c4669..8f8009d29cd 100644 --- a/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java +++ b/src/test/java/org/tron/common/runtime/vm/EnergyWhenSendAndTransferTest.java @@ -11,7 +11,7 @@ import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.TVMTestResult; -import org.tron.common.runtime.TVMTestUtils; +import org.tron.common.runtime.TvmTestUtils; import org.tron.common.storage.DepositImpl; import org.tron.common.utils.FileUtil; import org.tron.core.Constant; @@ -105,9 +105,9 @@ public void callValueTest() totalBalance - value - expectEnergyUsageTotal * 100); /* =================================== CALL simpleCall() =================================== */ - byte[] triggerData = TVMTestUtils.parseABI("simpleCall()", null); - result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + byte[] triggerData = TvmTestUtils.parseAbi("simpleCall()", null); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, 0, feeLimit, dbManager, null); long expectEnergyUsageTotal2 = 7370; @@ -116,9 +116,9 @@ public void callValueTest() totalBalance - value - (expectEnergyUsageTotal + expectEnergyUsageTotal2) * 100); /* =================================== CALL complexCall() =================================== */ - triggerData = TVMTestUtils.parseABI("complexCall()", null); - result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + triggerData = TvmTestUtils.parseAbi("complexCall()", null); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, 0, feeLimit, dbManager, null); long expectEnergyUsageTotal3 = 9459; @@ -181,9 +181,9 @@ public void sendTest() totalBalance - value - expectEnergyUsageTotal * 100); /* =================================== CALL doSend() =================================== */ - byte[] triggerData = TVMTestUtils.parseABI("doSend()", null); - result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + byte[] triggerData = TvmTestUtils.parseAbi("doSend()", null); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, 0, feeLimit, dbManager, null); long expectEnergyUsageTotal2 = 7025; @@ -215,9 +215,9 @@ public void transferTest() totalBalance - value - expectEnergyUsageTotal * 100); /* =================================== CALL doSend() =================================== */ - byte[] triggerData = TVMTestUtils.parseABI("doTransfer()", null); - result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + byte[] triggerData = TvmTestUtils.parseAbi("doTransfer()", null); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, 0, feeLimit, dbManager, null); long expectEnergyUsageTotal2 = 7030; @@ -238,8 +238,8 @@ public TVMTestResult deployCallValueTestContract(long value, long feeLimit, String code = "608060405261000c61004e565b604051809103906000f080158015610028573d6000803e3d6000fd5b5060008054600160a060020a031916600160a060020a039290921691909117905561005d565b60405160d68061020b83390190565b61019f8061006c6000396000f3006080604052600436106100325763ffffffff60e060020a60003504166306ce93af811461003757806340de221c1461004e575b600080fd5b34801561004357600080fd5b5061004c610063565b005b34801561005a57600080fd5b5061004c610103565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663cd95478c600a6003906040518363ffffffff1660e060020a0281526004016020604051808303818589803b1580156100d357600080fd5b5088f11580156100e7573d6000803e3d6000fd5b5050505050506040513d60208110156100ff57600080fd5b5050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b993e5e2600a6003906040518363ffffffff1660e060020a0281526004016020604051808303818589803b1580156100d357600080fd00a165627a7a72305820cb5f172ca9f81235a8b33ee1ddef9dd1b398644cf61228569356ff051bfaf3d10029608060405260c4806100126000396000f30060806040526004361060485763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663b993e5e28114604d578063cd95478c146065575b600080fd5b6053606b565b60408051918252519081900360200190f35b60536070565b602a90565b6000805b600a81101560945760008181526020819052604090208190556001016074565b50905600a165627a7a723058205ded543feb546472be4e116e713a2d46b8dafc823ca31256e67a1be92a6752730029"; String libraryAddressPair = null; - return TVMTestUtils - .deployContractAndReturnTVMTestResult(contractName, address, ABI, code, + return TvmTestUtils + .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair, dbManager, null); @@ -254,8 +254,8 @@ public TVMTestResult deploySendAndTransferTestContract(long value, long feeLimit String code = "608060405261000c61004e565b604051809103906000f080158015610028573d6000803e3d6000fd5b5060008054600160a060020a031916600160a060020a039290921691909117905561005d565b604051606f806101c583390190565b6101598061006c6000396000f3006080604052600436106100565763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166312065fe0811461005b57806333182e8f14610082578063e3d237f914610099575b600080fd5b34801561006757600080fd5b506100706100ae565b60408051918252519081900360200190f35b34801561008e57600080fd5b506100976100b3565b005b3480156100a557600080fd5b506100976100f9565b303190565b6000805460405173ffffffffffffffffffffffffffffffffffffffff90911691906127109082818181858883f193505050501580156100f6573d6000803e3d6000fd5b50565b6000805460405173ffffffffffffffffffffffffffffffffffffffff90911691906127109082818181858883f150505050505600a165627a7a72305820677efa58ed7b277b589fe6626cb77f930caeb0f75c3ab638bfe07292db961a8200296080604052605e8060116000396000f3006080604052600160008181526020527fada5013122d395ba3c54772283fb069b10426056ef8ca54750cb9bb552a59e7d550000a165627a7a7230582029b27c10c1568d590fa66bc0b7d42537a314c78d028f59a188fa411f7fc15c4f0029"; String libraryAddressPair = null; - return TVMTestUtils - .deployContractAndReturnTVMTestResult(contractName, address, ABI, code, + return TvmTestUtils + .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair, dbManager, null); diff --git a/src/test/java/org/tron/common/runtime/vm/EnergyWhenTimeoutStyleTest.java b/src/test/java/org/tron/common/runtime/vm/EnergyWhenTimeoutStyleTest.java index 0c4b2fdf987..c3f456c798f 100644 --- a/src/test/java/org/tron/common/runtime/vm/EnergyWhenTimeoutStyleTest.java +++ b/src/test/java/org/tron/common/runtime/vm/EnergyWhenTimeoutStyleTest.java @@ -11,7 +11,7 @@ import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.TVMTestResult; -import org.tron.common.runtime.TVMTestUtils; +import org.tron.common.runtime.TvmTestUtils; import org.tron.common.runtime.vm.program.Program.OutOfEnergyException; import org.tron.common.runtime.vm.program.Program.OutOfTimeException; import org.tron.common.storage.DepositImpl; @@ -106,10 +106,10 @@ public void endlessLoopTest() /* =================================== CALL setVote(uint256) =================================== */ String params = "0000000000000000000000000000000000000000000000000000000000000003"; - byte[] triggerData = TVMTestUtils.parseABI("setVote(uint256)", params); + byte[] triggerData = TvmTestUtils.parseAbi("setVote(uint256)", params); boolean haveException = false; - result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, value, feeLimit, dbManager, null); long expectEnergyUsageTotal2 = feeLimit / 100; @@ -130,8 +130,8 @@ public TVMTestResult deployEndlessLoopContract(long value, long feeLimit, String code = "608060405234801561001057600080fd5b506000808190555060fa806100266000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630242f35114604e578063230796ae146076575b600080fd5b348015605957600080fd5b50606060a0565b6040518082815260200191505060405180910390f35b348015608157600080fd5b50609e6004803603810190808035906020019092919050505060a9565b005b60008054905090565b806000819055505b60011560cb576001600080828254019250508190555060b1565b505600a165627a7a72305820290a38c9bbafccaf6c7f752ab56d229e354da767efb72715ee9fdb653b9f4b6c0029"; String libraryAddressPair = null; - return TVMTestUtils - .deployContractAndReturnTVMTestResult(contractName, address, ABI, code, + return TvmTestUtils + .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair, dbManager, null); diff --git a/src/test/java/org/tron/common/runtime/vm/ExtCodeHashTest.java b/src/test/java/org/tron/common/runtime/vm/ExtCodeHashTest.java new file mode 100644 index 00000000000..b2f101fcb5f --- /dev/null +++ b/src/test/java/org/tron/common/runtime/vm/ExtCodeHashTest.java @@ -0,0 +1,118 @@ +package org.tron.common.runtime.vm; + +import java.math.BigInteger; +import java.util.Arrays; +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; +import org.spongycastle.util.encoders.Hex; +import org.testng.Assert; +import org.tron.common.runtime.TVMTestResult; +import org.tron.common.runtime.TvmTestUtils; +import org.tron.common.runtime.config.VMConfig; +import org.tron.core.Wallet; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; +import org.tron.core.exception.ReceiptCheckErrException; +import org.tron.core.exception.VMIllegalException; +import org.tron.protos.Protocol.Transaction; +import stest.tron.wallet.common.client.utils.AbiUtil; + +@Slf4j +public class ExtCodeHashTest extends VMTestBase { +/* +pragma solidity ^0.5.0; +contract TestExtCodeHash { + + function getCodeHashByAddr(address _addr) public view returns (bytes32 _hash) { + assembly { + _hash := extcodehash(_addr) + } + } + function getCodeHashByUint(uint256 _addr) public view returns (bytes32 _hash) { + assembly { + _hash := extcodehash(_addr) + } + } +} +*/ + + @Test + public void testExtCodeHash() + throws ContractExeException, ReceiptCheckErrException, VMIllegalException, ContractValidateException { + VMConfig.initAllowTvmConstantinople(1); + String contractName = "TestExtCodeHash"; + byte[] address = Hex.decode(OWNER_ADDRESS); + String ABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"_addr\",\"type\":\"uint256\"}],\"name\":\"getCodeHashByUint\",\"outputs\":[{\"name\":\"_hash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"getCodeHashByAddr\",\"outputs\":[{\"name\":\"_hash\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]"; + String factoryCode = "608060405234801561001057600080fd5b5061010d806100206000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80637b77fd191460375780637d5e422d146076575b600080fd5b606060048036036020811015604b57600080fd5b810190808035906020019092919050505060cb565b6040518082815260200191505060405180910390f35b60b560048036036020811015608a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505060d6565b6040518082815260200191505060405180910390f35b6000813f9050919050565b6000813f905091905056fea165627a7a723058200f30933f006db4e1adeee12c030b87e720dad3cb169769159fc56ec25d9af66f0029"; + long value = 0; + long fee = 100000000; + long consumeUserResourcePercent = 0; + + // deploy contract + Transaction trx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( + contractName, address, ABI, factoryCode, value, fee, consumeUserResourcePercent, null); + byte[] factoryAddress = Wallet.generateContractAddress(trx); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootDeposit, null); + Assert.assertNull(runtime.getRuntimeError()); + + // Trigger contract method: getCodeHashByAddr(address) + String methodByAddr = "getCodeHashByAddr(address)"; + String nonexistentAccount = "27k66nycZATHzBasFT9782nTsYWqVtxdtAc"; + String hexInput = AbiUtil.parseMethod(methodByAddr, Arrays.asList(nonexistentAccount)); + TVMTestResult result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), + factoryAddress, Hex.decode(hexInput), 0, fee, manager, null); + Assert.assertNull(result.getRuntime().getRuntimeError()); + + byte[] returnValue = result.getRuntime().getResult().getHReturn(); + // check deployed contract + Assert.assertEquals(Hex.toHexString(returnValue), + "0000000000000000000000000000000000000000000000000000000000000000"); + + // trigger deployed contract + String existentAccount = "27WtBq2KoSy5v8VnVZBZHHJcDuWNiSgjbE3"; + hexInput = AbiUtil.parseMethod(methodByAddr, Arrays.asList(existentAccount)); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), + factoryAddress, Hex.decode(hexInput), 0, fee, manager, null); + Assert.assertNull(result.getRuntime().getRuntimeError()); + + returnValue = result.getRuntime().getResult().getHReturn(); + // check deployed contract + Assert.assertEquals(Hex.toHexString(returnValue), + "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"); + + // trigger deployed contract + String methodByUint = "getCodeHashByUint(uint256)"; + byte[] fullHexAddr = new DataWord(factoryAddress).getData(); + hexInput = AbiUtil.parseMethod(methodByUint, Hex.toHexString(fullHexAddr), true); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), + factoryAddress, Hex.decode(hexInput), 0, fee, manager, null); + Assert.assertNull(result.getRuntime().getRuntimeError()); + + returnValue = result.getRuntime().getResult().getHReturn(); + // check deployed contract + Assert.assertEquals(Hex.toHexString(returnValue), + "0837cd5e284138b633cd976ea6fcb719d61d7bc33d946ec5a2d0c7da419a0bd4"); + + // trigger deployed contract + BigInteger bigIntAddr = new DataWord(factoryAddress).sValue(); + String bigIntAddrChange = BigInteger.valueOf(2).pow(160).add(bigIntAddr).toString(16); + fullHexAddr = new DataWord(bigIntAddrChange).getData(); + hexInput = AbiUtil.parseMethod(methodByUint, Hex.toHexString(fullHexAddr), true); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), + factoryAddress, Hex.decode(hexInput), 0, fee, manager, null); + Assert.assertNull(result.getRuntime().getRuntimeError()); + + returnValue = result.getRuntime().getResult().getHReturn(); + // check deployed contract + Assert.assertEquals(Hex.toHexString(returnValue), + "0837cd5e284138b633cd976ea6fcb719d61d7bc33d946ec5a2d0c7da419a0bd4"); + + } + +} + + diff --git a/src/test/java/org/tron/common/runtime/vm/InternalTransactionCallTest.java b/src/test/java/org/tron/common/runtime/vm/InternalTransactionCallTest.java index b4e91723fc6..fb2b81518d3 100644 --- a/src/test/java/org/tron/common/runtime/vm/InternalTransactionCallTest.java +++ b/src/test/java/org/tron/common/runtime/vm/InternalTransactionCallTest.java @@ -11,7 +11,7 @@ import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.Runtime; -import org.tron.common.runtime.TVMTestUtils; +import org.tron.common.runtime.TvmTestUtils; import org.tron.common.storage.DepositImpl; import org.tron.common.utils.FileUtil; import org.tron.core.Constant; @@ -89,14 +89,14 @@ public void callTest() String params = Hex.toHexString(new DataWord(new DataWord(contractBAddress).getLast20Bytes()).getData()) + "0000000000000000000000000000000000000000000000000000000000000003"; - byte[] triggerData = TVMTestUtils.parseABI("callTest(address,uint256)", params); - TVMTestUtils.triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), + byte[] triggerData = TvmTestUtils.parseAbi("callTest(address,uint256)", params); + TvmTestUtils.triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), contractAAddress, triggerData, 0, 1000000000, deposit, null); /* =================================== CALL numberForB() to check A's numberForB =================================== */ - byte[] triggerData2 = TVMTestUtils.parseABI("numberForB()", ""); - runtime = TVMTestUtils + byte[] triggerData2 = TvmTestUtils.parseAbi("numberForB()", ""); + runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), contractAAddress, triggerData2, 0, 1000000000, deposit, null); @@ -105,8 +105,8 @@ public void callTest() "0000000000000000000000000000000000000000000000000000000000000000"); /* =================================== CALL senderForB() to check A's senderForB =================================== */ - byte[] triggerData3 = TVMTestUtils.parseABI("senderForB()", ""); - runtime = TVMTestUtils + byte[] triggerData3 = TvmTestUtils.parseAbi("senderForB()", ""); + runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), contractAAddress, triggerData3, 0, 1000000000, deposit, null); @@ -115,8 +115,8 @@ public void callTest() "0000000000000000000000000000000000000000000000000000000000000000"); /* =================================== CALL numberForB() to check B's numberForB =================================== */ - byte[] triggerData4 = TVMTestUtils.parseABI("numberForB()", ""); - runtime = TVMTestUtils + byte[] triggerData4 = TvmTestUtils.parseAbi("numberForB()", ""); + runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), contractBAddress, triggerData4, 0, 1000000000, deposit, null); @@ -125,8 +125,8 @@ public void callTest() "0000000000000000000000000000000000000000000000000000000000000003"); /* =================================== CALL senderForB() to check B's senderForB =================================== */ - byte[] triggerData5 = TVMTestUtils.parseABI("senderForB()", ""); - runtime = TVMTestUtils + byte[] triggerData5 = TvmTestUtils.parseAbi("senderForB()", ""); + runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), contractBAddress, triggerData5, 0, 1000000000, deposit, null); @@ -149,14 +149,14 @@ public void delegateCallTest() String params = Hex.toHexString(new DataWord(new DataWord(contractBAddress).getLast20Bytes()).getData()) + "0000000000000000000000000000000000000000000000000000000000000003"; - byte[] triggerData = TVMTestUtils.parseABI("delegatecallTest(address,uint256)", params); - TVMTestUtils.triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), + byte[] triggerData = TvmTestUtils.parseAbi("delegatecallTest(address,uint256)", params); + TvmTestUtils.triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), contractAAddress, triggerData, 0, 1000000000, deposit, null); /* =================================== CALL numberForB() to check A's numberForB =================================== */ - byte[] triggerData2 = TVMTestUtils.parseABI("numberForB()", ""); - runtime = TVMTestUtils + byte[] triggerData2 = TvmTestUtils.parseAbi("numberForB()", ""); + runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), contractAAddress, triggerData2, 0, 1000000000, deposit, null); @@ -165,8 +165,8 @@ public void delegateCallTest() "0000000000000000000000000000000000000000000000000000000000000003"); /* =================================== CALL senderForB() to check A's senderForB =================================== */ - byte[] triggerData3 = TVMTestUtils.parseABI("senderForB()", ""); - runtime = TVMTestUtils + byte[] triggerData3 = TvmTestUtils.parseAbi("senderForB()", ""); + runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), contractAAddress, triggerData3, 0, 1000000000, deposit, null); @@ -175,8 +175,8 @@ public void delegateCallTest() Hex.toHexString(new DataWord(new DataWord(OWNER_ADDRESS).getLast20Bytes()).getData())); /* =================================== CALL numberForB() to check B's numberForB =================================== */ - byte[] triggerData4 = TVMTestUtils.parseABI("numberForB()", ""); - runtime = TVMTestUtils + byte[] triggerData4 = TvmTestUtils.parseAbi("numberForB()", ""); + runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), contractBAddress, triggerData4, 0, 1000000000, deposit, null); @@ -185,8 +185,8 @@ public void delegateCallTest() "0000000000000000000000000000000000000000000000000000000000000000"); /* =================================== CALL senderForB() to check B's senderForB =================================== */ - byte[] triggerData5 = TVMTestUtils.parseABI("senderForB()", ""); - runtime = TVMTestUtils + byte[] triggerData5 = TvmTestUtils.parseAbi("senderForB()", ""); + runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), contractBAddress, triggerData5, 0, 1000000000, deposit, null); @@ -210,14 +210,14 @@ public void callCodeTest() String params = Hex.toHexString(new DataWord(new DataWord(contractBAddress).getLast20Bytes()).getData()) + "0000000000000000000000000000000000000000000000000000000000000003"; - byte[] triggerData = TVMTestUtils.parseABI("callcodeTest(address,uint256)", params); - TVMTestUtils.triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), + byte[] triggerData = TvmTestUtils.parseAbi("callcodeTest(address,uint256)", params); + TvmTestUtils.triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), contractAAddress, triggerData, 0, 1000000000, deposit, null); /* =================================== CALL numberForB() to check A's numberForB =================================== */ - byte[] triggerData2 = TVMTestUtils.parseABI("numberForB()", ""); - runtime = TVMTestUtils + byte[] triggerData2 = TvmTestUtils.parseAbi("numberForB()", ""); + runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), contractAAddress, triggerData2, 0, 1000000000, deposit, null); @@ -226,8 +226,8 @@ public void callCodeTest() "0000000000000000000000000000000000000000000000000000000000000003"); /* =================================== CALL senderForB() to check A's senderForB =================================== */ - byte[] triggerData3 = TVMTestUtils.parseABI("senderForB()", ""); - runtime = TVMTestUtils + byte[] triggerData3 = TvmTestUtils.parseAbi("senderForB()", ""); + runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), contractAAddress, triggerData3, 0, 1000000000, deposit, null); @@ -236,8 +236,8 @@ public void callCodeTest() Hex.toHexString(new DataWord(new DataWord(contractAAddress).getLast20Bytes()).getData())); /* =================================== CALL numberForB() to check B's numberForB =================================== */ - byte[] triggerData4 = TVMTestUtils.parseABI("numberForB()", ""); - runtime = TVMTestUtils + byte[] triggerData4 = TvmTestUtils.parseAbi("numberForB()", ""); + runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), contractBAddress, triggerData4, 0, 1000000000, deposit, null); @@ -246,8 +246,8 @@ public void callCodeTest() "0000000000000000000000000000000000000000000000000000000000000000"); /* =================================== CALL senderForB() to check B's senderForB =================================== */ - byte[] triggerData5 = TVMTestUtils.parseABI("senderForB()", ""); - runtime = TVMTestUtils + byte[] triggerData5 = TvmTestUtils.parseAbi("senderForB()", ""); + runtime = TvmTestUtils .triggerContractWholeProcessReturnContractAddress(Hex.decode(OWNER_ADDRESS), contractBAddress, triggerData5, 0, 1000000000, deposit, null); @@ -296,7 +296,7 @@ public byte[] deployAContractandGetItsAddress() long consumeUserResourcePercent = 0; String libraryAddressPair = null; - byte[] contractAddress = TVMTestUtils + byte[] contractAddress = TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair, deposit, null); @@ -328,7 +328,7 @@ public byte[] deployBContractAndGetItsAddress() long consumeUserResourcePercent = 0; String libraryAddressPair = null; - byte[] contractAddress = TVMTestUtils + byte[] contractAddress = TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair, deposit, null); diff --git a/src/test/java/org/tron/common/runtime/vm/StorageTest.java b/src/test/java/org/tron/common/runtime/vm/StorageTest.java index c918835b497..248e66fe0fa 100644 --- a/src/test/java/org/tron/common/runtime/vm/StorageTest.java +++ b/src/test/java/org/tron/common/runtime/vm/StorageTest.java @@ -1,35 +1,23 @@ package org.tron.common.runtime.vm; -import java.io.File; import java.util.Arrays; import lombok.extern.slf4j.Slf4j; -import org.junit.After; -import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.spongycastle.util.encoders.Hex; import org.testng.Assert; -import org.tron.common.application.ApplicationFactory; -import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.TVMTestResult; -import org.tron.common.runtime.TVMTestUtils; +import org.tron.common.runtime.TvmTestUtils; import org.tron.common.runtime.config.VMConfig; import org.tron.common.storage.Deposit; import org.tron.common.storage.DepositImpl; -import org.tron.common.utils.FileUtil; -import org.tron.core.Constant; import org.tron.core.Wallet; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.Parameter.ForkBlockVersionConsts; -import org.tron.core.config.args.Args; -import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.ReceiptCheckErrException; import org.tron.core.exception.VMIllegalException; -import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Transaction; -import org.tron.common.runtime.Runtime; @Slf4j public class StorageTest extends VMTestBase { @@ -108,10 +96,10 @@ public void contractWriteAndDeleteStorage() long consumeUserResourcePercent = 0; // deploy contract - Transaction trx = TVMTestUtils.generateDeploySmartContractAndGetTransaction( + Transaction trx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( contractName, address, ABI, code, value, fee, consumeUserResourcePercent, null); byte[] contractAddress = Wallet.generateContractAddress(trx); - runtime = TVMTestUtils.processTransactionAndReturnRuntime(trx, rootDeposit, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootDeposit, null); Assert.assertNull(runtime.getRuntimeError()); // write storage @@ -119,18 +107,18 @@ public void contractWriteAndDeleteStorage() // 1,"abc" String params1 = "0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000036162630000000000000000000000000000000000000000000000000000000000"; String params2 = "0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000033132330000000000000000000000000000000000000000000000000000000000"; - byte[] triggerData = TVMTestUtils.parseABI("testPut(uint256,string)", params1); - TVMTestResult result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + byte[] triggerData = TvmTestUtils.parseAbi("testPut(uint256,string)", params1); + TVMTestResult result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, 0, fee, manager, null); Assert.assertNull(result.getRuntime().getRuntimeError()); // overwrite storage with same value // testPut(uint256,string) 1,"abc" - triggerData = TVMTestUtils.parseABI("testPut(uint256,string)", params1); - result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + triggerData = TvmTestUtils.parseAbi("testPut(uint256,string)", params1); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, 0, fee, manager, null); Assert.assertNull(result.getRuntime().getRuntimeError()); @@ -139,9 +127,9 @@ public void contractWriteAndDeleteStorage() // overwrite storage with same value // testPut(uint256,string) 1,"123" - triggerData = TVMTestUtils.parseABI("testPut(uint256,string)", params2); - result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + triggerData = TvmTestUtils.parseAbi("testPut(uint256,string)", params2); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, 0, fee, manager, null); Assert.assertNull(result.getRuntime().getRuntimeError()); @@ -149,10 +137,10 @@ public void contractWriteAndDeleteStorage() // delete storage // testDelete(uint256) 1 - triggerData = TVMTestUtils.parseABI("testDelete(uint256)", + triggerData = TvmTestUtils.parseAbi("testDelete(uint256)", "0000000000000000000000000000000000000000000000000000000000000001"); - result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, 0, fee, manager, null); Assert.assertNull(result.getRuntime().getRuntimeError()); Assert.assertNull(result.getRuntime().getResult().getException()); diff --git a/src/test/java/org/tron/common/runtime/vm/TimeBenchmarkTest.java b/src/test/java/org/tron/common/runtime/vm/TimeBenchmarkTest.java index 0ec186eb9d1..294ac1900c0 100644 --- a/src/test/java/org/tron/common/runtime/vm/TimeBenchmarkTest.java +++ b/src/test/java/org/tron/common/runtime/vm/TimeBenchmarkTest.java @@ -12,7 +12,7 @@ import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.TVMTestResult; -import org.tron.common.runtime.TVMTestUtils; +import org.tron.common.runtime.TvmTestUtils; import org.tron.common.storage.DepositImpl; import org.tron.common.utils.FileUtil; import org.tron.core.Constant; @@ -101,8 +101,8 @@ public void timeBenchmark() String code = "608060405234801561001057600080fd5b506101ba806100206000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633c7fdc701461005157806361047ff414610092575b600080fd5b34801561005d57600080fd5b5061007c600480360381019080803590602001909291905050506100d3565b6040518082815260200191505060405180910390f35b34801561009e57600080fd5b506100bd60048036038101908080359060200190929190505050610124565b6040518082815260200191505060405180910390f35b60006100de82610124565b90507f71e71a8458267085d5ab16980fd5f114d2d37f232479c245d523ce8d23ca40ed8282604051808381526020018281526020019250505060405180910390a1919050565b60008060008060008086141561013d5760009450610185565b600186141561014f5760019450610185565b600093506001925060009150600290505b85811115156101815782840191508293508192508080600101915050610160565b8194505b505050509190505600a165627a7a72305820637e163344c180cd57f4b3a01b07a5267ad54811a5a2858b5d67330a2724ee680029"; String libraryAddressPair = null; - TVMTestResult result = TVMTestUtils - .deployContractAndReturnTVMTestResult(contractName, address, ABI, code, + TVMTestResult result = TvmTestUtils + .deployContractAndReturnTvmTestResult(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, libraryAddressPair, dbManager, null); @@ -114,9 +114,9 @@ public void timeBenchmark() byte[] contractAddress = result.getContractAddress(); /* ====================================================================== */ - byte[] triggerData = TVMTestUtils.parseABI("fibonacciNotify(uint)", ""); - result = TVMTestUtils - .triggerContractAndReturnTVMTestResult(Hex.decode(OWNER_ADDRESS), + byte[] triggerData = TvmTestUtils.parseAbi("fibonacciNotify(uint)", ""); + result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, 0, feeLimit, dbManager, null); long expectEnergyUsageTotal2 = 110; diff --git a/src/test/java/org/tron/common/runtime/vm/TransferFailedEnergyTest.java b/src/test/java/org/tron/common/runtime/vm/TransferFailedEnergyTest.java new file mode 100644 index 00000000000..e4c33d3c017 --- /dev/null +++ b/src/test/java/org/tron/common/runtime/vm/TransferFailedEnergyTest.java @@ -0,0 +1,306 @@ +package org.tron.common.runtime.vm; + +import java.util.Collections; +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.ToString; +import org.junit.Test; +import org.spongycastle.util.encoders.Hex; +import org.testng.Assert; +import org.tron.common.runtime.TVMTestResult; +import org.tron.common.runtime.TvmTestUtils; +import org.tron.common.runtime.config.VMConfig; +import org.tron.common.runtime.vm.program.ProgramResult; +import org.tron.core.Wallet; +import org.tron.core.capsule.ReceiptCapsule; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; +import org.tron.core.exception.ReceiptCheckErrException; +import org.tron.core.exception.VMIllegalException; +import org.tron.protos.Protocol.Transaction; +import org.tron.protos.Protocol.Transaction.Result.contractResult; +import stest.tron.wallet.common.client.utils.AbiUtil; + +public class TransferFailedEnergyTest extends VMTestBase { +/* +pragma solidity ^0.5.4; +contract EnergyOfTransferFailedTest { + constructor() payable public { + + } + // InsufficientBalance + function testTransferTrxInsufficientBalance() payable public{ + msg.sender.transfer(10); + } + + function testSendTrxInsufficientBalance() payable public{ + msg.sender.send(10); + } + + function testTransferTokenInsufficientBalance(trcToken tokenId) payable public{ + msg.sender.transferToken(10, tokenId); + } + + function testCallTrxInsufficientBalance(address payable caller) public { + caller.call.value(10)(abi.encodeWithSignature("test()")); + } + + function testCreateTrxInsufficientBalance() payable public { + (new Caller).value(10)(); + } + + // NonexistentTarget + function testTransferTrxNonexistentTarget(address payable nonexistentTarget) payable public { + require(address(this).balance >= 10); + nonexistentTarget.transfer(10); + } + + function testTransferTokenNonexistentTarget(address payable nonexistentTarget, trcToken tokenId) payable public { + require(address(this).balance >= 10); + nonexistentTarget.transferToken(10, tokenId); + } + + function testCallTrxNonexistentTarget(address payable nonexistentTarget) payable public { + require(address(this).balance >= 10); + nonexistentTarget.call.value(10)(abi.encodeWithSignature("test()")); + } + + function testSuicideNonexistentTarget(address payable nonexistentTarget) payable public { + selfdestruct(nonexistentTarget); + } + + // target is self + function testTransferTrxSelf() payable public{ + require(address(this).balance >= 10); + address payable self = address(uint160(address(this))); + self.transfer(10); + } + + function testSendTrxSelf() payable public{ + require(address(this).balance >= 10); + address payable self = address(uint160(address(this))); + self.send(10); + } + + function testTransferTokenSelf(trcToken tokenId) payable public{ + require(address(this).balance >= 10); + address payable self = address(uint160(address(this))); + self.transferToken(10, tokenId); + } +} + + + +contract Caller { + constructor() payable public {} + function test() payable public {} +} + */ + +/* +// 0.4.25 +contract EnergyOfTransferFailedTest { + + constructor() payable public { + + } + + // InsufficientBalance + function testTransferTrxInsufficientBalance() payable public{ + msg.sender.transfer(10); + } + + function testSendTrxInsufficientBalance() payable public{ + msg.sender.send(10); + } + + function testTransferTokenInsufficientBalance(trcToken tokenId) payable public{ + msg.sender.transferToken(10, tokenId); + } + + function testCallTrxInsufficientBalance(address caller) payable public { + caller.call.value(10)(abi.encodeWithSignature("test()")); + } + + function testCreateTrxInsufficientBalance() payable public { + (new Caller).value(10)(); + } + + // NonexistentTarget + function testTransferTrxNonexistentTarget(address nonexistentTarget) payable public { + require(address(this).balance >= 10); + nonexistentTarget.transfer(10); + } + + function testTransferTokenNonexistentTarget(address nonexistentTarget, trcToken tokenId) payable public { + require(address(this).balance >= 10); + nonexistentTarget.transferToken(10, tokenId); + } + + function testCallTrxNonexistentTarget(address nonexistentTarget) public { + require(address(this).balance >= 10); + nonexistentTarget.call.value(10)(abi.encodeWithSignature("test()")); + } + + function testSuicideNonexistentTarget(address nonexistentTarget) public { + selfdestruct(nonexistentTarget); + } + + // target is self + function testTransferTrxSelf() payable public{ + require(address(this).balance >= 10); + address self = address(uint160(address(this))); + self.transfer(10); + } + + function testSendTrxSelf() payable public{ + require(address(this).balance >= 10); + address self = address(uint160(address(this))); + self.send(10); + } + + function testTransferTokenSelf(trcToken tokenId) payable public{ + require(address(this).balance >= 10); + address self = address(uint160(address(this))); + self.transferToken(10, tokenId); + } +} + + + +contract Caller { + constructor() payable public {} + function test() payable public {} +} + */ + + @Data + @AllArgsConstructor + @ToString + static class TestCase { + String method; + List params; + boolean allEnergy; + contractResult receiptResult; + } + + private static final String nonExistAddress = "27k66nycZATHzBasFT9782nTsYWqVtxdtAc"; // 21 char + + TestCase[] testCasesAfterAllowTvmConstantinop = { + new TestCase("testTransferTrxSelf()", Collections.emptyList(), false, contractResult.TRANSFER_FAILED), + new TestCase("testSendTrxSelf()", Collections.emptyList(), false, contractResult.TRANSFER_FAILED), + new TestCase("testSuicideNonexistentTarget(address)", Collections.singletonList(nonExistAddress), false, contractResult.TRANSFER_FAILED), + new TestCase("testTransferTrxNonexistentTarget(address)", Collections.singletonList(nonExistAddress), false, contractResult.TRANSFER_FAILED), + new TestCase("testCallTrxNonexistentTarget(address)", Collections.singletonList(nonExistAddress), false, contractResult.TRANSFER_FAILED), + }; + + TestCase[] testCasesBeforeAllowTvmConstantinop = { + new TestCase("testTransferTrxSelf()", Collections.emptyList(), true, contractResult.UNKNOWN), + new TestCase("testSendTrxSelf()", Collections.emptyList(), true, contractResult.UNKNOWN), + new TestCase("testSuicideNonexistentTarget(address)", Collections.singletonList(nonExistAddress), true, contractResult.UNKNOWN), + new TestCase("testTransferTrxNonexistentTarget(address)", Collections.singletonList(nonExistAddress), true, contractResult.UNKNOWN), + new TestCase("testCallTrxNonexistentTarget(address)", Collections.singletonList(nonExistAddress), true, contractResult.UNKNOWN), + }; + + TestCase[] testCasesInsufficientBalance = { + new TestCase("testTransferTrxInsufficientBalance()", Collections.emptyList(), false, contractResult.REVERT), + new TestCase("testSendTrxInsufficientBalance()", Collections.emptyList(), false, contractResult.SUCCESS), + new TestCase("testCreateTrxInsufficientBalance()", Collections.emptyList(), false, contractResult.REVERT), + new TestCase("testCallTrxInsufficientBalance()", Collections.emptyList(), false, contractResult.REVERT), + new TestCase("testTransferTokenInsufficientBalance(trcToken)", Collections.singletonList(1000001), false, contractResult.REVERT), + }; + + + + @Test + public void testTransferFailedAfterAllowTvmConstantinopl() + throws ContractExeException, ReceiptCheckErrException, VMIllegalException, ContractValidateException { + VMConfig.initAllowTvmTransferTrc10(1); + VMConfig.initAllowTvmConstantinople(1); + + String contractName = "EnergyOfTransferFailedTest"; + byte[] address = Hex.decode(OWNER_ADDRESS); + String ABI = "[]"; + String code = "608060405261060c806100136000396000f3fe6080604052600436106100c4576000357c01000000000000000000000000000000000000000000000000000000009004806344e51c131161008157806344e51c131461017c57806362098f73146101a257806387a9d735146101aa5780639d24d299146101c75780639da1bf8a146101f3578063f10d5077146101fb576100c4565b806307ed3f71146100c957806308e4ab99146100d35780630d0def85146100db5780630de991bb1461012857806317b6ad5b1461013057806322970e1814610156575b600080fd5b6100d1610218565b005b6100d1610244565b3480156100e757600080fd5b50d380156100f457600080fd5b50d2801561010157600080fd5b506100d16004803603602081101561011857600080fd5b5035600160a060020a0316610272565b6100d161036f565b6100d16004803603602081101561014657600080fd5b5035600160a060020a03166103ad565b6100d16004803603602081101561016c57600080fd5b5035600160a060020a03166103b9565b6100d16004803603602081101561019257600080fd5b5035600160a060020a03166103fa565b6100d1610409565b6100d1600480360360208110156101c057600080fd5b5035610423565b6100d1600480360360408110156101dd57600080fd5b50600160a060020a038135169060200135610496565b6100d16104c1565b6100d16004803603602081101561021157600080fd5b50356104ed565b6040513390600090600a9082818181858883f19350505050158015610241573d6000803e3d6000fd5b50565b600a60405161025290610550565b6040518091039082f08015801561026d573d6000803e3d6000fd5b505050565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167ff8a8fd6d0000000000000000000000000000000000000000000000000000000017815291518151600160a060020a03851693600a9392918291908083835b602083106103025780518252601f1990920191602091820191016102e3565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114610364576040519150601f19603f3d011682016040523d82523d6000602084013e610369565b606091505b50505050565b600a3031101561037e57600080fd5b60405130908190600090600a9082818181858883f193505050501580156103a9573d6000803e3d6000fd5b5050565b80600160a060020a0316ff5b600a303110156103c857600080fd5b604051600160a060020a03821690600090600a9082818181858883f193505050501580156103a9573d6000803e3d6000fd5b600a3031101561027257600080fd5b6040513390600090600a9082818181858883f15050505050565b600a3031101561043257600080fd5b30806000600a848015801561044657600080fd5b50806780000000000000001115801561045e57600080fd5b5080620f42401015801561047157600080fd5b50604051600081818185878a8ad094505050505015801561026d573d6000803e3d6000fd5b600a303110156104a557600080fd5b600160a060020a0382166000600a838015801561044657600080fd5b600a303110156104d057600080fd5b60405130908190600090600a9082818181858883f1505050505050565b336000600a838015801561050057600080fd5b50806780000000000000001115801561051857600080fd5b5080620f42401015801561052b57600080fd5b50604051600081818185878a8ad09450505050501580156103a9573d6000803e3d6000fd5b60848061055d8339019056fe608060405260738060116000396000f3fe6080604052600436106038577c01000000000000000000000000000000000000000000000000000000006000350463f8a8fd6d8114603d575b600080fd5b60436045565b005b56fea165627a7a72305820ae73d633cf81f32e8c6917d5faea925dd9c04abcecf002617d6ec1440f1349c90029a165627a7a723058201f0cab76b7df6e1900e7524fd40e9257a915692888b74c2e2e68df9d9a4a5a910029"; + long value = 100000; + long fee = 100000000; + long consumeUserResourcePercent = 0; + +// deploy contract + Transaction trx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( + contractName, address, ABI, code, value, fee, consumeUserResourcePercent, null); + byte[] addressWithSufficientBalance = Wallet.generateContractAddress(trx); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootDeposit, null); + Assert.assertNull(runtime.getRuntimeError()); + + for (TestCase testCase : testCasesAfterAllowTvmConstantinop) { + checkResult(testCase, addressWithSufficientBalance); + } + + trx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( + contractName, address, ABI, code, 0, fee, consumeUserResourcePercent, null); + byte[] addressWithoutBalance = Wallet.generateContractAddress(trx); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootDeposit, null); + Assert.assertNull(runtime.getRuntimeError()); + + for (TestCase testCase : testCasesInsufficientBalance) { + checkResult(testCase, addressWithoutBalance); + } + } + + @Test + public void testTransferFailedBeforeAllowTvmConstantinopl() + throws ContractExeException, ReceiptCheckErrException, VMIllegalException, ContractValidateException { + VMConfig.initAllowTvmTransferTrc10(1); + VMConfig.initAllowTvmConstantinople(0); + + String contractName = "EnergyOfTransferFailedTest"; + byte[] address = Hex.decode(OWNER_ADDRESS); + String ABI = "[]"; + String code = "6080604052610537806100136000396000f3006080604052600436106100b95763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166307ed3f7181146100be57806308e4ab99146100c85780630d0def85146100d05780630de991bb146100e457806317b6ad5b146100ec57806322970e181461012757806344e51c131461013b57806362098f731461017657806387a9d7351461017e5780639d24d299146101895780639da1bf8a146101a0578063f10d5077146101a8575b600080fd5b6100c66101b3565b005b6100c66101df565b6100c6600160a060020a0360043516610209565b6100c66102d9565b3480156100f857600080fd5b50d3801561010557600080fd5b50d2801561011257600080fd5b506100c6600160a060020a036004351661031a565b6100c6600160a060020a0360043516610326565b34801561014757600080fd5b50d3801561015457600080fd5b50d2801561016157600080fd5b506100c6600160a060020a0360043516610367565b6100c6610376565b6100c6600435610390565b6100c6600160a060020a03600435166024356103d1565b6100c6610416565b6100c6600435610445565b6040513390600090600a9082818181858883f193505050501580156101dc573d6000803e3d6000fd5b50565b600a6101e9610472565b6040518091039082f080158015610204573d6000803e3d6000fd5b505050565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167ff8a8fd6d0000000000000000000000000000000000000000000000000000000017815291518151600160a060020a03851693600a93929182919080838360005b8381101561029457818101518382015260200161027c565b50505050905090810190601f1680156102c15780820380516001836020036101000a031916815260200191505b5091505060006040518083038185875af15050505050565b6000600a303110156102ea57600080fd5b5060405130908190600090600a9082818181858883f19350505050158015610316573d6000803e3d6000fd5b5050565b80600160a060020a0316ff5b600a3031101561033557600080fd5b604051600160a060020a03821690600090600a9082818181858883f19350505050158015610316573d6000803e3d6000fd5b600a3031101561020957600080fd5b6040513390600090600a9082818181858883f15050505050565b6000600a303110156103a157600080fd5b5060405130908190600090600a9085908381818185878a84d0945050505050158015610204573d6000803e3d6000fd5b600a303110156103e057600080fd5b604051600160a060020a03831690600090600a9084908381818185878a84d0945050505050158015610204573d6000803e3d6000fd5b6000600a3031101561042757600080fd5b5060405130908190600090600a9082818181858883f1505050505050565b6040513390600090600a9084908381818185878a84d0945050505050158015610316573d6000803e3d6000fd5b604051608a80610482833901905600608060405260798060116000396000f300608060405260043610603e5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663f8a8fd6d81146043575b600080fd5b6049604b565b005b5600a165627a7a7230582066a52bc3564dc2aaabcf2d0f05931fdc34035835d12182e3140d5f3f7e5d73720029a165627a7a723058207a028d240821b50b5b91c64afed0a997bd46f353f5e8f374ee4823c19d0ed0130029"; + long value = 100000; + long fee = 100000000; + long consumeUserResourcePercent = 0; + +// deploy contract + Transaction trx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( + contractName, address, ABI, code, value, fee, consumeUserResourcePercent, null); + byte[] addressWithSufficientBalance = Wallet.generateContractAddress(trx); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootDeposit, null); + Assert.assertNull(runtime.getRuntimeError()); + + for (TestCase testCase : testCasesBeforeAllowTvmConstantinop) { + checkResult(testCase, addressWithSufficientBalance); + } + + trx = TvmTestUtils.generateDeploySmartContractAndGetTransaction( + contractName, address, ABI, code, 0, fee, consumeUserResourcePercent, null); + byte[] addressWithoutBalance = Wallet.generateContractAddress(trx); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(trx, rootDeposit, null); + Assert.assertNull(runtime.getRuntimeError()); + + for (TestCase testCase : testCasesInsufficientBalance) { + checkResult(testCase, addressWithoutBalance); + } + } + + private void checkResult(TestCase testCase, byte[] factoryAddress) + throws ContractExeException, ReceiptCheckErrException, VMIllegalException, ContractValidateException { + String hexInput = AbiUtil.parseMethod(testCase.getMethod(), testCase.getParams()); + long fee = 100000000; + long allEnergy = 1000000; + TVMTestResult result = TvmTestUtils + .triggerContractAndReturnTvmTestResult(Hex.decode(OWNER_ADDRESS), + factoryAddress, Hex.decode(hexInput), 0, fee, manager, null); + ProgramResult programResult = result.getRuntime().getResult(); + ReceiptCapsule receiptCapsule = result.getReceipt(); + Assert.assertEquals(receiptCapsule.getResult(), testCase.getReceiptResult(), + testCase.getMethod()); + if (testCase.allEnergy) { + Assert.assertEquals(programResult.getEnergyUsed(), 1000000, testCase.getMethod()); + } else { + Assert.assertTrue(programResult.getEnergyUsed() < allEnergy, testCase.getMethod()); + } + } +} diff --git a/src/test/java/org/tron/common/runtime/vm/TransferTokenTest.java b/src/test/java/org/tron/common/runtime/vm/TransferTokenTest.java index c331aceeaa0..29b1298883a 100644 --- a/src/test/java/org/tron/common/runtime/vm/TransferTokenTest.java +++ b/src/test/java/org/tron/common/runtime/vm/TransferTokenTest.java @@ -11,7 +11,7 @@ import org.tron.common.application.ApplicationFactory; import org.tron.common.application.TronApplicationContext; import org.tron.common.runtime.Runtime; -import org.tron.common.runtime.TVMTestUtils; +import org.tron.common.runtime.TvmTestUtils; import org.tron.common.runtime.config.VMConfig; import org.tron.common.storage.DepositImpl; import org.tron.common.utils.ByteArray; @@ -128,17 +128,17 @@ public void TransferTokenTest() String params = "000000000000000000000000548794500882809695a8a687866e76d4271a1abc" + Hex.toHexString(new DataWord(id).getData()) + "0000000000000000000000000000000000000000000000000000000000000009"; //TRANSFER_TO, 100001, 9 - byte[] triggerData = TVMTestUtils.parseABI(selectorStr, params); + byte[] triggerData = TvmTestUtils.parseAbi(selectorStr, params); /* 2. Test trigger with tokenValue and tokenId, also test internal transaction transferToken function */ long triggerCallValue = 100; long feeLimit = 100000000; long tokenValue = 8; - Transaction transaction = TVMTestUtils + Transaction transaction = TvmTestUtils .generateTriggerSmartContractAndGetTransaction(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, triggerCallValue, feeLimit, tokenValue, id); - runtime = TVMTestUtils.processTransactionAndReturnRuntime(transaction, dbManager, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(transaction, dbManager, null); org.testng.Assert.assertNull(runtime.getRuntimeError()); Assert.assertEquals(100 + tokenValue - 9, @@ -156,12 +156,12 @@ public void TransferTokenTest() dbManager.getAccountStore().put(contractAddress, changeAccountCapsule); String selectorStr2 = "suicide(address)"; String params2 = "000000000000000000000000548794500882809695a8a687866e76d4271a1abc"; //TRANSFER_TO - byte[] triggerData2 = TVMTestUtils.parseABI(selectorStr2, params2); - Transaction transaction2 = TVMTestUtils + byte[] triggerData2 = TvmTestUtils.parseAbi(selectorStr2, params2); + Transaction transaction2 = TvmTestUtils .generateTriggerSmartContractAndGetTransaction(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData2, triggerCallValue, feeLimit, 0, id); - runtime = TVMTestUtils.processTransactionAndReturnRuntime(transaction2, dbManager, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(transaction2, dbManager, null); org.testng.Assert.assertNull(runtime.getRuntimeError()); Assert.assertEquals(100 + tokenValue - 9 + 9, dbManager.getAccountStore().get(Hex.decode(TRANSFER_TO)).getAssetMapV2() @@ -194,7 +194,7 @@ private byte[] deployTransferTokenContract(long id) long tokenValue = 100; long tokenId = id; - byte[] contractAddress = TVMTestUtils + byte[] contractAddress = TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, null, tokenValue, tokenId, deposit, null); @@ -218,14 +218,14 @@ public void TransferTokenSingleInstructionTimeTest() String params = "000000000000000000000000548794500882809695a8a687866e76d4271a1abc" + Hex.toHexString(new DataWord(id).getData()) + "0000000000000000000000000000000000000000000000000000000000000002"; //TRANSFER_TO, 100001, 9 - byte[] triggerData = TVMTestUtils.parseABI(selectorStr, params); - Transaction transaction = TVMTestUtils + byte[] triggerData = TvmTestUtils.parseAbi(selectorStr, params); + Transaction transaction = TvmTestUtils .generateTriggerSmartContractAndGetTransaction(Hex.decode(OWNER_ADDRESS), contractAddress, triggerData, triggerCallValue, feeLimit, tokenValue, id); long start = System.nanoTime() / 1000; - runtime = TVMTestUtils.processTransactionAndReturnRuntime(transaction, dbManager, null); + runtime = TvmTestUtils.processTransactionAndReturnRuntime(transaction, dbManager, null); long end = System.nanoTime() / 1000; System.err.println("running time:" + (end - start)); Assert.assertTrue((end - start) < 50_0000); @@ -253,7 +253,7 @@ private byte[] deployTransferTokenPerformanceContract(long id) long tokenValue = 1000_000; long tokenId = id; - byte[] contractAddress = TVMTestUtils + byte[] contractAddress = TvmTestUtils .deployContractWholeProcessReturnContractAddress(contractName, address, ABI, code, value, feeLimit, consumeUserResourcePercent, null, tokenValue, tokenId, deposit, null); diff --git a/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java b/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java index 630008d354b..67c94908166 100644 --- a/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java +++ b/src/test/java/org/tron/common/storage/leveldb/LevelDbDataSourceImplTest.java @@ -53,13 +53,15 @@ public class LevelDbDataSourceImplTest { private byte[] value4 = "40000".getBytes(); private byte[] value5 = "50000".getBytes(); private byte[] value6 = "60000".getBytes(); + private byte[] value7 = "70000".getBytes(); + private byte[] key1 = "00000001aa".getBytes(); private byte[] key2 = "00000002aa".getBytes(); private byte[] key3 = "00000003aa".getBytes(); private byte[] key4 = "00000004aa".getBytes(); private byte[] key5 = "00000005aa".getBytes(); private byte[] key6 = "00000006aa".getBytes(); - + private byte[] key7 = "00000003ab".getBytes(); @Before public void initDb() { Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); @@ -272,4 +274,22 @@ public void getValuesPrev() { dataSource.resetDb(); dataSource.closeDB(); } + + @Test + public void getPrevious() { + LevelDbDataSourceImpl dataSource = new LevelDbDataSourceImpl( + Args.getInstance().getOutputDirectory(), "test_getPrevious_key"); + dataSource.initDB(); + dataSource.resetDb(); + putSomeKeyValue(dataSource); + dataSource.putData(key7, value7); + + Map seekKeyLimitNext = dataSource.getPrevious(key3, Long.MAX_VALUE, Long.SIZE / Byte.SIZE); + Assert.assertEquals("getPrevious1", 4, seekKeyLimitNext.size()); + + seekKeyLimitNext = dataSource.getPrevious(key3, Long.MAX_VALUE, 10); + Assert.assertEquals("getPrevious2", 3, seekKeyLimitNext.size()); + dataSource.resetDb(); + dataSource.closeDB(); + } } \ No newline at end of file diff --git a/src/test/java/org/tron/core/WalletTest.java b/src/test/java/org/tron/core/WalletTest.java index e893c2af8c9..ef4beba632c 100644 --- a/src/test/java/org/tron/core/WalletTest.java +++ b/src/test/java/org/tron/core/WalletTest.java @@ -58,6 +58,7 @@ import org.tron.protos.Protocol.Block; import org.tron.protos.Protocol.BlockHeader; import org.tron.protos.Protocol.BlockHeader.raw; +//import org.tron.protos.Protocol.DeferredTransaction; import org.tron.protos.Protocol.Exchange; import org.tron.protos.Protocol.Proposal; import org.tron.protos.Protocol.Transaction; @@ -76,6 +77,7 @@ public class WalletTest { public static final String ACCOUNT_ADDRESS_THREE = "343434a9cf"; public static final String ACCOUNT_ADDRESS_FOUR = "454545a9cf"; public static final String ACCOUNT_ADDRESS_FIVE = "565656a9cf"; + public static final String ACCOUNT_ADDRESS_SIX = "12344349cf"; private static Block block1; private static Block block2; private static Block block3; @@ -101,6 +103,8 @@ public class WalletTest { private static Transaction transaction3; private static Transaction transaction4; private static Transaction transaction5; + private static Transaction transaction6; + //private static DeferredTransaction deferredTransaction; public static final long TRANSACTION_TIMESTAMP_ONE = DateTime.now().minusDays(4).getMillis(); public static final long TRANSACTION_TIMESTAMP_TWO = DateTime.now().minusDays(3).getMillis(); public static final long TRANSACTION_TIMESTAMP_THREE = DateTime.now().minusDays(2).getMillis(); @@ -146,6 +150,10 @@ private static void initTransaction() { getBuildTransferContract(ACCOUNT_ADDRESS_FIVE, ACCOUNT_ADDRESS_ONE), TRANSACTION_TIMESTAMP_FIVE, BLOCK_NUM_FIVE); addTransactionToStore(transaction5); + transaction6 = getBuildTransaction( + getBuildTransferContract(ACCOUNT_ADDRESS_ONE, ACCOUNT_ADDRESS_SIX), + TRANSACTION_TIMESTAMP_FIVE, BLOCK_NUM_FIVE); + addTransactionToStore(transaction5); } private static void addTransactionToStore(Transaction transaction) { @@ -157,10 +165,12 @@ private static void addTransactionToStore(Transaction transaction) { private static Transaction getBuildTransaction( TransferContract transferContract, long transactionTimestamp, long refBlockNum) { return Transaction.newBuilder().setRawData( - Transaction.raw.newBuilder().setTimestamp(transactionTimestamp).setRefBlockNum(refBlockNum) + Transaction.raw.newBuilder().setTimestamp(transactionTimestamp) + .setRefBlockNum(refBlockNum) .addContract( Contract.newBuilder().setType(ContractType.TransferContract) - .setParameter(Any.pack(transferContract)).build()).build()).build(); + .setParameter(Any.pack(transferContract)).build()).build()) + .build(); } private static TransferContract getBuildTransferContract(String ownerAddress, String toAddress) { @@ -330,19 +340,24 @@ public void getBlocksByLimit() { @Test public void getTransactionById() { Transaction transactionById = wallet.getTransactionById( - ByteString.copyFrom(new TransactionCapsule(transaction1).getTransactionId().getBytes())); + ByteString + .copyFrom(new TransactionCapsule(transaction1).getTransactionId().getBytes())); Assert.assertEquals("getTransactionById1", transaction1, transactionById); transactionById = wallet.getTransactionById( - ByteString.copyFrom(new TransactionCapsule(transaction2).getTransactionId().getBytes())); + ByteString + .copyFrom(new TransactionCapsule(transaction2).getTransactionId().getBytes())); Assert.assertEquals("getTransactionById2", transaction2, transactionById); transactionById = wallet.getTransactionById( - ByteString.copyFrom(new TransactionCapsule(transaction3).getTransactionId().getBytes())); + ByteString + .copyFrom(new TransactionCapsule(transaction3).getTransactionId().getBytes())); Assert.assertEquals("getTransactionById3", transaction3, transactionById); transactionById = wallet.getTransactionById( - ByteString.copyFrom(new TransactionCapsule(transaction4).getTransactionId().getBytes())); + ByteString + .copyFrom(new TransactionCapsule(transaction4).getTransactionId().getBytes())); Assert.assertEquals("getTransactionById4", transaction4, transactionById); transactionById = wallet.getTransactionById( - ByteString.copyFrom(new TransactionCapsule(transaction5).getTransactionId().getBytes())); + ByteString + .copyFrom(new TransactionCapsule(transaction5).getTransactionId().getBytes())); Assert.assertEquals("getTransactionById5", transaction5, transactionById); } diff --git a/src/test/java/org/tron/core/actuator/AccountPermissionUpdateActuatorTest.java b/src/test/java/org/tron/core/actuator/AccountPermissionUpdateActuatorTest.java index 5e8bf35a26a..fefc1d79113 100644 --- a/src/test/java/org/tron/core/actuator/AccountPermissionUpdateActuatorTest.java +++ b/src/test/java/org/tron/core/actuator/AccountPermissionUpdateActuatorTest.java @@ -34,6 +34,7 @@ import org.tron.protos.Protocol.Permission; import org.tron.protos.Protocol.Permission.PermissionType; import org.tron.protos.Protocol.Transaction.Result.code; +import org.tron.protos.Protocol.Transaction.Contract.ContractType; @Slf4j public class AccountPermissionUpdateActuatorTest { @@ -1099,4 +1100,100 @@ public void witnessPermissionOperationNeedless() { "Witness permission needn't operations", "Witness permission needn't operations"); } + + @Test + public void checkAvailableContractTypeCorrespondingToCode() { + // note: The aim of this test case is to show how the current codes work. + // The default value is 7fff1fc0037e0000000000000000000000000000000000000000000000000000, + // and it should call the addSystemContractAndSetPermission to add new contract type + String validContractType = "7fff1fc0037e0000000000000000000000000000000000000000000000000000"; + + byte[] availableContractType = new byte[32]; + for (ContractType contractType : ContractType.values()) { + if (contractType == org.tron.protos.Protocol.Transaction.Contract.ContractType.UNRECOGNIZED + || contractType == ContractType.ClearABIContract + //|| contractType == ContractType.CancelDeferredTransactionContract + ) { + continue; + } + int id = contractType.getNumber(); + System.out.println("id is " + id); + availableContractType[id / 8] |= (1 << id % 8); + } + + System.out.println(ByteArray.toHexString(availableContractType)); + + Assert.assertEquals(ByteArray.toHexString(availableContractType), validContractType); + + } + + @Test + public void checkActiveDefaultOperationsCorrespondingToCode() { + // note: The aim of this test case is to show how the current codes work. + // The default value is 7fff1fc0033e0000000000000000000000000000000000000000000000000000, + // and it should call the addSystemContractAndSetPermission to add new contract type + String validContractType = "7fff1fc0033e0000000000000000000000000000000000000000000000000000"; + + byte[] availableContractType = new byte[32]; + for (ContractType contractType : ContractType.values()) { + if (contractType == org.tron.protos.Protocol.Transaction.Contract.ContractType.UNRECOGNIZED + || contractType == ContractType.AccountPermissionUpdateContract + || contractType == ContractType.ClearABIContract + //|| contractType == ContractType.CancelDeferredTransactionContract + ) { + continue; + } + int id = contractType.getNumber(); + System.out.println("id is " + id); + availableContractType[id / 8] |= (1 << id % 8); + } + + System.out.println(ByteArray.toHexString(availableContractType)); + + Assert.assertEquals(ByteArray.toHexString(availableContractType), validContractType); + + } + + + @Test + public void checkAvailableContractType() { + String validContractType = "7fff1fc0037e0100000000000000000000000000000000000000000000000000"; + + byte[] availableContractType = new byte[32]; + for (ContractType contractType : ContractType.values()) { + if (contractType == org.tron.protos.Protocol.Transaction.Contract.ContractType.UNRECOGNIZED) { + continue; + } + int id = contractType.getNumber(); + System.out.println("id is " + id); + availableContractType[id / 8] |= (1 << id % 8); + } + + System.out.println(ByteArray.toHexString(availableContractType)); + + Assert.assertEquals(ByteArray.toHexString(availableContractType), validContractType); + + } + + @Test + public void checkActiveDefaultOperations() { + String validContractType = "7fff1fc0033e0100000000000000000000000000000000000000000000000000"; + + byte[] availableContractType = new byte[32]; + for (ContractType contractType : ContractType.values()) { + if (contractType == org.tron.protos.Protocol.Transaction.Contract.ContractType.UNRECOGNIZED + || contractType == ContractType.AccountPermissionUpdateContract) { + continue; + } + int id = contractType.getNumber(); + System.out.println("id is " + id); + availableContractType[id / 8] |= (1 << id % 8); + } + + System.out.println(ByteArray.toHexString(availableContractType)); + + Assert.assertEquals(ByteArray.toHexString(availableContractType), validContractType); + + } + } \ No newline at end of file diff --git a/src/test/java/org/tron/core/actuator/ClearABIContractActuatorTest.java b/src/test/java/org/tron/core/actuator/ClearABIContractActuatorTest.java new file mode 100644 index 00000000000..469c8c9654c --- /dev/null +++ b/src/test/java/org/tron/core/actuator/ClearABIContractActuatorTest.java @@ -0,0 +1,273 @@ +package org.tron.core.actuator; + +import static junit.framework.TestCase.fail; +import static stest.tron.wallet.common.client.utils.PublicMethed.jsonStr2Abi; + +import com.google.protobuf.Any; +import com.google.protobuf.ByteString; +import java.io.File; +import lombok.extern.slf4j.Slf4j; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.runtime.config.VMConfig; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.FileUtil; +import org.tron.common.utils.StringUtil; +import org.tron.core.Constant; +import org.tron.core.Wallet; +import org.tron.core.capsule.AccountCapsule; +import org.tron.core.capsule.ContractCapsule; +import org.tron.core.capsule.TransactionResultCapsule; +import org.tron.core.config.DefaultConfig; +import org.tron.core.config.args.Args; +import org.tron.core.db.Manager; +import org.tron.core.exception.ContractExeException; +import org.tron.core.exception.ContractValidateException; +import org.tron.protos.Contract; +import org.tron.protos.Protocol; +import org.tron.protos.Protocol.SmartContract.ABI; + + +@Slf4j +public class ClearABIContractActuatorTest { + + private static TronApplicationContext context; + private static Manager dbManager; + private static final String dbPath = "output_clearabicontract_test"; + private static final String OWNER_ADDRESS; + private static final String OWNER_ADDRESS_ACCOUNT_NAME = "test_account"; + private static final String SECOND_ACCOUNT_ADDRESS; + private static final String OWNER_ADDRESS_NOTEXIST; + private static final String OWNER_ADDRESS_INVALID = "aaaa"; + private static final String SMART_CONTRACT_NAME = "smart_contarct"; + private static final String CONTRACT_ADDRESS = "111111"; + private static final String NO_EXIST_CONTRACT_ADDRESS = "2222222"; + private static final ABI SOURCE_ABI = jsonStr2Abi( + "[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}]"); + private static final ABI TARGET_ABI = ABI.getDefaultInstance(); + + static { + Args.setParam(new String[]{"--output-directory", dbPath}, Constant.TEST_CONF); + context = new TronApplicationContext(DefaultConfig.class); + OWNER_ADDRESS = Wallet.getAddressPreFixString() + "abd4b9367799eaa3197fecb144eb71de1e049abc"; + OWNER_ADDRESS_NOTEXIST = + Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d4271a1abc"; + SECOND_ACCOUNT_ADDRESS = + Wallet.getAddressPreFixString() + "548794500882809695a8a687866e76d427122222"; + } + + /** + * Init data. + */ + @BeforeClass + public static void init() { + VMConfig.initAllowTvmConstantinople(1); + dbManager = context.getBean(Manager.class); + } + + /** + * create temp Capsule test need. + */ + @Before + public void createCapsule() { + // address in accountStore and the owner of contract + AccountCapsule accountCapsule = + new AccountCapsule( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)), + ByteString.copyFromUtf8(OWNER_ADDRESS_ACCOUNT_NAME), + Protocol.AccountType.Normal); + dbManager.getAccountStore().put(ByteArray.fromHexString(OWNER_ADDRESS), accountCapsule); + + // smartContarct in contractStore + Protocol.SmartContract.Builder builder = Protocol.SmartContract.newBuilder(); + builder.setName(SMART_CONTRACT_NAME); + builder.setOriginAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))); + builder.setContractAddress(ByteString.copyFrom(ByteArray.fromHexString(CONTRACT_ADDRESS))); + builder.setAbi(SOURCE_ABI); + dbManager.getContractStore().put( + ByteArray.fromHexString(CONTRACT_ADDRESS), + new ContractCapsule(builder.build())); + + // address in accountStore not the owner of contract + AccountCapsule secondAccount = + new AccountCapsule( + ByteString.copyFrom(ByteArray.fromHexString(SECOND_ACCOUNT_ADDRESS)), + ByteString.copyFromUtf8(OWNER_ADDRESS_ACCOUNT_NAME), + Protocol.AccountType.Normal); + dbManager.getAccountStore().put(ByteArray.fromHexString(SECOND_ACCOUNT_ADDRESS), secondAccount); + + // address does not exist in accountStore + dbManager.getAccountStore().delete(ByteArray.fromHexString(OWNER_ADDRESS_NOTEXIST)); + } + + /** + * Release resources. + */ + @AfterClass + public static void destroy() { + Args.clearParam(); + context.destroy(); + if (FileUtil.deleteDir(new File(dbPath))) { + logger.info("Release resources successful."); + } else { + logger.info("Release resources failure."); + } + } + + private Any getContract(String accountAddress, String contractAddress) { + return Any.pack( + Contract.ClearABIContract.newBuilder() + .setOwnerAddress(StringUtil.hexString2ByteString(accountAddress)) + .setContractAddress(StringUtil.hexString2ByteString(contractAddress)) + .build()); + } + + @Test + public void successClearABIContract() { + ClearABIContractActuator actuator = + new ClearABIContractActuator( + getContract(OWNER_ADDRESS, CONTRACT_ADDRESS), dbManager); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + + // assert result state and consume_user_resource_percent + Assert.assertEquals(ret.getInstance().getRet(), Protocol.Transaction.Result.code.SUCESS); + Assert.assertEquals( + dbManager.getContractStore().get(ByteArray.fromHexString(CONTRACT_ADDRESS)). + getInstance().getAbi(), + TARGET_ABI); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + @Test + public void invalidAddress() { + ClearABIContractActuator actuator = + new ClearABIContractActuator( + getContract(OWNER_ADDRESS_INVALID, CONTRACT_ADDRESS), dbManager); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + + fail("Invalid address"); + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("Invalid address", e.getMessage()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + @Test + public void noExistAccount() { + ClearABIContractActuator actuator = + new ClearABIContractActuator( + getContract(OWNER_ADDRESS_NOTEXIST, CONTRACT_ADDRESS), dbManager); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + + fail("Account[" + OWNER_ADDRESS_NOTEXIST + "] not exists"); + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("Account[" + OWNER_ADDRESS_NOTEXIST + "] not exists", e.getMessage()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + @Test + public void noExistContract() { + ClearABIContractActuator actuator = + new ClearABIContractActuator( + getContract(OWNER_ADDRESS, NO_EXIST_CONTRACT_ADDRESS), dbManager); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + + fail("Contract not exists"); + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("Contract not exists", e.getMessage()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + @Test + public void callerNotContractOwner() { + ClearABIContractActuator actuator = + new ClearABIContractActuator( + getContract(SECOND_ACCOUNT_ADDRESS, CONTRACT_ADDRESS), dbManager); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + actuator.validate(); + actuator.execute(ret); + + fail("Account[" + SECOND_ACCOUNT_ADDRESS + "] is not the owner of the contract"); + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals( + "Account[" + SECOND_ACCOUNT_ADDRESS + "] is not the owner of the contract", + e.getMessage()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + @Test + public void twiceUpdateSettingContract() { + ClearABIContractActuator actuator = + new ClearABIContractActuator( + getContract(OWNER_ADDRESS, CONTRACT_ADDRESS), dbManager); + + ClearABIContractActuator secondActuator = + new ClearABIContractActuator( + getContract(OWNER_ADDRESS, CONTRACT_ADDRESS), dbManager); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + try { + // first + actuator.validate(); + actuator.execute(ret); + + Assert.assertEquals(ret.getInstance().getRet(), Protocol.Transaction.Result.code.SUCESS); + Assert.assertEquals( + dbManager.getContractStore().get(ByteArray.fromHexString(CONTRACT_ADDRESS)). + getInstance().getAbi(), + TARGET_ABI); + + // second + secondActuator.validate(); + secondActuator.execute(ret); + + Assert.assertEquals(ret.getInstance().getRet(), Protocol.Transaction.Result.code.SUCESS); + Assert.assertEquals( + dbManager.getContractStore().get(ByteArray.fromHexString(CONTRACT_ADDRESS)). + getInstance().getAbi(), + TARGET_ABI); + + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } +} diff --git a/src/test/java/org/tron/core/actuator/FreezeBalanceActuatorTest.java b/src/test/java/org/tron/core/actuator/FreezeBalanceActuatorTest.java index e9c087741f7..9525a3a5c3b 100644 --- a/src/test/java/org/tron/core/actuator/FreezeBalanceActuatorTest.java +++ b/src/test/java/org/tron/core/actuator/FreezeBalanceActuatorTest.java @@ -195,6 +195,37 @@ public void testFreezeBalanceForEnergy() { } } + + @Test + public void testFreezeDelegatedBalanceForBandwidthWithContractAddress() { + AccountCapsule receiverCapsule = + new AccountCapsule( + ByteString.copyFromUtf8("receiver"), + ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS)), + AccountType.Contract, + initBalance); + dbManager.getAccountStore().put(receiverCapsule.getAddress().toByteArray(), receiverCapsule); + + dbManager.getDynamicPropertiesStore().saveAllowTvmConstantinople(1); + + dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); + long frozenBalance = 1_000_000_000L; + long duration = 3; + FreezeBalanceActuator actuator = new FreezeBalanceActuator( + getDelegatedContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS, frozenBalance, duration), + dbManager); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + actuator.validate(); + actuator.execute(ret); + } catch (ContractValidateException e) { + Assert.assertEquals(e.getMessage(),"Do not allow delegate resources to contract addresses"); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + @Test public void testFreezeDelegatedBalanceForBandwidth() { dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); diff --git a/src/test/java/org/tron/core/actuator/ProposalCreateActuatorTest.java b/src/test/java/org/tron/core/actuator/ProposalCreateActuatorTest.java index ea4697073cb..0ae802d87ad 100644 --- a/src/test/java/org/tron/core/actuator/ProposalCreateActuatorTest.java +++ b/src/test/java/org/tron/core/actuator/ProposalCreateActuatorTest.java @@ -232,7 +232,7 @@ public void noWitness() { @Test public void invalidPara() { HashMap paras = new HashMap<>(); - paras.put(24L, 10000L); + paras.put(31L, 10000L); ProposalCreateActuator actuator = new ProposalCreateActuator(getContract(OWNER_ADDRESS_FIRST, paras), dbManager); TransactionResultCapsule ret = new TransactionResultCapsule(); diff --git a/src/test/java/org/tron/core/actuator/UnfreezeBalanceActuatorTest.java b/src/test/java/org/tron/core/actuator/UnfreezeBalanceActuatorTest.java index f9c4a113e32..1a4f1d291db 100644 --- a/src/test/java/org/tron/core/actuator/UnfreezeBalanceActuatorTest.java +++ b/src/test/java/org/tron/core/actuator/UnfreezeBalanceActuatorTest.java @@ -313,6 +313,108 @@ public void testUnfreezeDelegatedBalanceForBandwidth() { } } + @Test + public void testUnfreezeDelegatedBalanceForBandwidthWithDeletedReceiver() { + + dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + AccountCapsule owner = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + owner.setDelegatedFrozenBalanceForBandwidth(frozenBalance); + Assert.assertEquals(frozenBalance, owner.getTronPower()); + + AccountCapsule receiver = dbManager.getAccountStore() + .get(ByteArray.fromHexString(RECEIVER_ADDRESS)); + receiver.setAcquiredDelegatedFrozenBalanceForBandwidth(frozenBalance); + Assert.assertEquals(0L, receiver.getTronPower()); + + dbManager.getAccountStore().put(owner.createDbKey(), owner); + + //init DelegatedResourceCapsule + DelegatedResourceCapsule delegatedResourceCapsule = new DelegatedResourceCapsule( + owner.getAddress(), + receiver.getAddress() + ); + delegatedResourceCapsule.setFrozenBalanceForBandwidth( + frozenBalance, + now - 100L); + dbManager.getDelegatedResourceStore().put(DelegatedResourceCapsule + .createDbKey(ByteArray.fromHexString(OWNER_ADDRESS), + ByteArray.fromHexString(RECEIVER_ADDRESS)), delegatedResourceCapsule); + + //init DelegatedResourceAccountIndex + { + DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndex = new DelegatedResourceAccountIndexCapsule( + owner.getAddress()); + delegatedResourceAccountIndex + .addToAccount(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))); + dbManager.getDelegatedResourceAccountIndexStore() + .put(ByteArray.fromHexString(OWNER_ADDRESS), delegatedResourceAccountIndex); + } + + { + DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndex = new DelegatedResourceAccountIndexCapsule( + receiver.getAddress()); + delegatedResourceAccountIndex + .addFromAccount(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))); + dbManager.getDelegatedResourceAccountIndexStore() + .put(ByteArray.fromHexString(RECEIVER_ADDRESS), delegatedResourceAccountIndex); + } + + UnfreezeBalanceActuator actuator = new UnfreezeBalanceActuator( + getDelegatedContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS), dbManager); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + + + dbManager.getDynamicPropertiesStore().saveAllowTvmConstantinople(0); + dbManager.getAccountStore().delete(receiver.createDbKey()); + try { + actuator.validate(); + actuator.execute(ret); + } catch (ContractValidateException e) { + Assert.assertEquals(e.getMessage(),"Receiver Account[a0abd4b9367799eaa3197fecb144eb71de1e049150] not exists"); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + + dbManager.getDynamicPropertiesStore().saveAllowTvmConstantinople(1); + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + AccountCapsule ownerResult = + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + + Assert.assertEquals(initBalance + frozenBalance, ownerResult.getBalance()); + Assert.assertEquals(0L, ownerResult.getTronPower()); + Assert.assertEquals(0L, ownerResult.getDelegatedFrozenBalanceForBandwidth()); + + //check DelegatedResourceAccountIndex + DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsuleOwner = dbManager + .getDelegatedResourceAccountIndexStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + Assert + .assertEquals(0, delegatedResourceAccountIndexCapsuleOwner.getFromAccountsList().size()); + Assert.assertEquals(0, delegatedResourceAccountIndexCapsuleOwner.getToAccountsList().size()); + + DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsuleReceiver = dbManager + .getDelegatedResourceAccountIndexStore().get(ByteArray.fromHexString(RECEIVER_ADDRESS)); + Assert + .assertEquals(0, delegatedResourceAccountIndexCapsuleReceiver.getToAccountsList().size()); + Assert + .assertEquals(0, + delegatedResourceAccountIndexCapsuleReceiver.getFromAccountsList().size()); + + } catch (ContractValidateException e) { + logger.error("",e); + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + + } /** * when SameTokenName close,delegate balance frozen, unfreoze show error @@ -384,7 +486,6 @@ public void testUnfreezeDelegatedBalanceForBandwidthSameTokenNameClose() { } } - @Test public void testUnfreezeDelegatedBalanceForCpu() { dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); @@ -402,7 +503,7 @@ public void testUnfreezeDelegatedBalanceForCpu() { Assert.assertEquals(0L, receiver.getTronPower()); dbManager.getAccountStore().put(owner.createDbKey(), owner); - dbManager.getAccountStore().put(receiver.createDbKey(), receiver); + dbManager.getAccountStore().put(receiver.createDbKey(),receiver); DelegatedResourceCapsule delegatedResourceCapsule = new DelegatedResourceCapsule( owner.getAddress(), @@ -433,6 +534,72 @@ public void testUnfreezeDelegatedBalanceForCpu() { Assert.assertEquals(0L, ownerResult.getTronPower()); Assert.assertEquals(0L, ownerResult.getDelegatedFrozenBalanceForEnergy()); Assert.assertEquals(0L, receiverResult.getAllFrozenBalanceForEnergy()); + } catch (ContractValidateException e) { + logger.error("",e); + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } + + @Test + public void testUnfreezeDelegatedBalanceForCpuWithDeletedReceiver() { + dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + AccountCapsule owner = dbManager.getAccountStore() + .get(ByteArray.fromHexString(OWNER_ADDRESS)); + owner.addDelegatedFrozenBalanceForEnergy(frozenBalance); + Assert.assertEquals(frozenBalance, owner.getTronPower()); + + AccountCapsule receiver = dbManager.getAccountStore() + .get(ByteArray.fromHexString(RECEIVER_ADDRESS)); + receiver.addAcquiredDelegatedFrozenBalanceForEnergy(frozenBalance); + Assert.assertEquals(0L, receiver.getTronPower()); + + dbManager.getAccountStore().put(owner.createDbKey(), owner); + + DelegatedResourceCapsule delegatedResourceCapsule = new DelegatedResourceCapsule( + owner.getAddress(), + receiver.getAddress() + ); + delegatedResourceCapsule.setFrozenBalanceForEnergy( + frozenBalance, + now - 100L); + dbManager.getDelegatedResourceStore().put(DelegatedResourceCapsule + .createDbKey(ByteArray.fromHexString(OWNER_ADDRESS), + ByteArray.fromHexString(RECEIVER_ADDRESS)), delegatedResourceCapsule); + + UnfreezeBalanceActuator actuator = new UnfreezeBalanceActuator( + getDelegatedContractForCpu(OWNER_ADDRESS, RECEIVER_ADDRESS), dbManager); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + + dbManager.getDynamicPropertiesStore().saveAllowTvmConstantinople(0); + dbManager.getAccountStore().delete(receiver.createDbKey()); + + try { + actuator.validate(); + actuator.execute(ret); + } catch (ContractValidateException e) { + Assert.assertEquals(e.getMessage(),"Receiver Account[a0abd4b9367799eaa3197fecb144eb71de1e049150] not exists"); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + + dbManager.getDynamicPropertiesStore().saveAllowTvmConstantinople(1); + + try { + actuator.validate(); + actuator.execute(ret); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + AccountCapsule ownerResult = + dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + + Assert.assertEquals(initBalance + frozenBalance, ownerResult.getBalance()); + Assert.assertEquals(0L, ownerResult.getTronPower()); + Assert.assertEquals(0L, ownerResult.getDelegatedFrozenBalanceForEnergy()); } catch (ContractValidateException e) { Assert.assertFalse(e instanceof ContractValidateException); } catch (ContractExeException e) { diff --git a/src/test/java/org/tron/core/capsule/utils/BlockUtil.java b/src/test/java/org/tron/core/capsule/utils/BlockUtil.java index a2562896fd5..bcb967c1e43 100644 --- a/src/test/java/org/tron/core/capsule/utils/BlockUtil.java +++ b/src/test/java/org/tron/core/capsule/utils/BlockUtil.java @@ -3,15 +3,11 @@ import com.google.protobuf.ByteString; import java.util.List; -import java.util.Map; import java.util.stream.Collectors; import org.tron.common.utils.ByteArray; -import org.tron.common.utils.Sha256Hash; import org.tron.core.capsule.BlockCapsule; import org.tron.core.config.args.Args; import org.tron.core.config.args.GenesisBlock; -import org.tron.core.db.Manager; -import org.tron.core.witness.WitnessController; import org.tron.protos.Protocol.Transaction; public class BlockUtil { @@ -51,16 +47,4 @@ public static boolean isParentOf(BlockCapsule blockCapsule1, BlockCapsule blockC return blockCapsule1.getBlockId().equals(blockCapsule2.getParentHash()); } - public static BlockCapsule createTestBlockCapsule(Manager dbManager, long time, - long number, ByteString hash, Map addressToProvateKeys) { - WitnessController witnessController = dbManager.getWitnessController(); - ByteString witnessAddress = - witnessController.getScheduledWitness(witnessController.getSlotAtTime(time)); - BlockCapsule blockCapsule = new BlockCapsule(number, Sha256Hash.wrap(hash), time, - witnessAddress); - blockCapsule.generatedByMyself = true; - blockCapsule.setMerkleRoot(); - blockCapsule.sign(ByteArray.fromHexString(addressToProvateKeys.get(witnessAddress))); - return blockCapsule; - } } \ No newline at end of file diff --git a/src/test/java/org/tron/core/db/ManagerTest.java b/src/test/java/org/tron/core/db/ManagerTest.java index c93113a427c..abb482dcb7f 100755 --- a/src/test/java/org/tron/core/db/ManagerTest.java +++ b/src/test/java/org/tron/core/db/ManagerTest.java @@ -47,6 +47,9 @@ import org.tron.core.witness.WitnessController; import org.tron.protos.Contract.TransferContract; import org.tron.protos.Protocol.Account; +import org.tron.protos.Protocol.Block; +import org.tron.protos.Protocol.BlockHeader; +import org.tron.protos.Protocol.BlockHeader.raw; import org.tron.protos.Protocol.Transaction.Contract.ContractType; @Slf4j @@ -146,11 +149,6 @@ public void pushBlock() { Assert.assertTrue("pushBlock is error", false); } -// Assert.assertTrue( -// "containBlock is error", -// dbManager.containBlock( -// Sha256Hash.wrap(ByteArray.fromHexString(blockCapsule2.getBlockId().toString())))); - if (isUnlinked) { Assert.assertEquals("getBlockIdByNum is error", dbManager.getHeadBlockNum(), 0); } else { @@ -167,7 +165,6 @@ public void pushBlock() { Assert.assertTrue("hasBlocks is error", dbManager.hasBlocks()); } - // @Test public void updateWits() { int sizePrv = dbManager.getWitnesses().size(); dbManager @@ -175,7 +172,8 @@ public void updateWits() { .forEach( witnessAddress -> { logger.info( - "witness address is {}", ByteArray.toHexString(witnessAddress.toByteArray())); + "witness address is {}", + ByteArray.toHexString(witnessAddress.toByteArray())); }); logger.info("------------"); WitnessCapsule witnessCapsulef = @@ -196,7 +194,8 @@ public void updateWits() { .forEach( witnessAddress -> { logger.info( - "witness address is {}", ByteArray.toHexString(witnessAddress.toByteArray())); + "witness address is {}", + ByteArray.toHexString(witnessAddress.toByteArray())); }); logger.info("---------"); dbManager.getWitnessStore().put(witnessCapsulef.getAddress().toByteArray(), witnessCapsulef); @@ -208,7 +207,8 @@ public void updateWits() { .forEach( witnessAddress -> { logger.info( - "witness address is {}", ByteArray.toHexString(witnessAddress.toByteArray())); + "witness address is {}", + ByteArray.toHexString(witnessAddress.toByteArray())); }); int sizeTis = dbManager.getWitnesses().size(); Assert.assertEquals("update add witness size is ", 2, sizeTis - sizePrv); @@ -239,14 +239,16 @@ public void fork() createTestBlockCapsule( 1533529947843L + 3000, num + 1, - dbManager.getDynamicPropertiesStore().getLatestBlockHeaderHash().getByteString(), + dbManager.getDynamicPropertiesStore().getLatestBlockHeaderHash() + .getByteString(), addressToProvateKeys); BlockCapsule blockCapsule1 = createTestBlockCapsule( 1533529947843L + 3000, num + 1, - dbManager.getDynamicPropertiesStore().getLatestBlockHeaderHash().getByteString(), + dbManager.getDynamicPropertiesStore().getLatestBlockHeaderHash() + .getByteString(), addressToProvateKeys); dbManager.pushBlock(blockCapsule0); @@ -269,9 +271,11 @@ public void fork() Assert.assertEquals(dbManager.getBlockStore().size(), size + 3); Assert.assertEquals( - dbManager.getBlockIdByNum(dbManager.getHead().getNum() - 1), blockCapsule1.getBlockId()); + dbManager.getBlockIdByNum(dbManager.getHead().getNum() - 1), + blockCapsule1.getBlockId()); Assert.assertEquals( - dbManager.getBlockIdByNum(dbManager.getHead().getNum() - 2), blockCapsule1.getParentHash()); + dbManager.getBlockIdByNum(dbManager.getHead().getNum() - 2), + blockCapsule1.getParentHash()); Assert.assertEquals( blockCapsule2.getBlockId(), @@ -308,14 +312,16 @@ public void doNotSwitch() createTestBlockCapsule( 1533529947843L + 3000, num + 1, - dbManager.getDynamicPropertiesStore().getLatestBlockHeaderHash().getByteString(), + dbManager.getDynamicPropertiesStore().getLatestBlockHeaderHash() + .getByteString(), addressToProvateKeys); BlockCapsule blockCapsule1 = createTestBlockCapsule( 1533529947843L + 3001, num + 1, - dbManager.getDynamicPropertiesStore().getLatestBlockHeaderHash().getByteString(), + dbManager.getDynamicPropertiesStore().getLatestBlockHeaderHash() + .getByteString(), addressToProvateKeys); logger.info("******block0:" + blockCapsule0); @@ -350,7 +356,8 @@ public void doNotSwitch() BlockCapsule blockCapsule3 = createTestBlockCapsule(1533529947843L + 9000, dbManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() + 1, - dbManager.getDynamicPropertiesStore().getLatestBlockHeaderHash().getByteString(), + dbManager.getDynamicPropertiesStore().getLatestBlockHeaderHash() + .getByteString(), addressToProvateKeys); logger.info("******block3:" + blockCapsule3); dbManager.pushBlock(blockCapsule3); @@ -359,7 +366,8 @@ public void doNotSwitch() dbManager.getDynamicPropertiesStore().getLatestBlockHeaderHash()); Assert.assertEquals(blockCapsule3.getBlockId(), dbManager.getBlockStore() - .get(dbManager.getDynamicPropertiesStore().getLatestBlockHeaderHash().getBytes()) + .get(dbManager.getDynamicPropertiesStore().getLatestBlockHeaderHash() + .getBytes()) .getBlockId()); BlockCapsule blockCapsule4 = @@ -373,7 +381,8 @@ public void doNotSwitch() dbManager.getDynamicPropertiesStore().getLatestBlockHeaderHash()); Assert.assertEquals(blockCapsule4.getBlockId(), dbManager.getBlockStore() - .get(dbManager.getDynamicPropertiesStore().getLatestBlockHeaderHash().getBytes()) + .get(dbManager.getDynamicPropertiesStore().getLatestBlockHeaderHash() + .getBytes()) .getBlockId()); } @@ -430,14 +439,16 @@ public void switchBack() createTestBlockCapsule( 1533529947843L + 3000, num + 1, - dbManager.getDynamicPropertiesStore().getLatestBlockHeaderHash().getByteString(), + dbManager.getDynamicPropertiesStore().getLatestBlockHeaderHash() + .getByteString(), addressToProvateKeys); BlockCapsule blockCapsule1 = createTestBlockCapsule( 1533529947843L + 3000, num + 1, - dbManager.getDynamicPropertiesStore().getLatestBlockHeaderHash().getByteString(), + dbManager.getDynamicPropertiesStore().getLatestBlockHeaderHash() + .getByteString(), addressToProvateKeys); dbManager.pushBlock(blockCapsule0); @@ -468,7 +479,8 @@ public void switchBack() dbManager.getDynamicPropertiesStore().getLatestBlockHeaderHash()); Assert.assertEquals(blockCapsule3.getBlockId(), dbManager.getBlockStore() - .get(dbManager.getDynamicPropertiesStore().getLatestBlockHeaderHash().getBytes()) + .get(dbManager.getDynamicPropertiesStore().getLatestBlockHeaderHash() + .getBytes()) .getBlockId()); BlockCapsule blockCapsule4 = @@ -482,7 +494,8 @@ public void switchBack() dbManager.getDynamicPropertiesStore().getLatestBlockHeaderHash()); Assert.assertEquals(blockCapsule4.getBlockId(), dbManager.getBlockStore() - .get(dbManager.getDynamicPropertiesStore().getLatestBlockHeaderHash().getBytes()) + .get(dbManager.getDynamicPropertiesStore().getLatestBlockHeaderHash() + .getBytes()) .getBlockId()); } diff --git a/src/test/java/org/tron/core/db/TransactionTraceTest.java b/src/test/java/org/tron/core/db/TransactionTraceTest.java index 8a46e57fb46..2aed5074daf 100644 --- a/src/test/java/org/tron/core/db/TransactionTraceTest.java +++ b/src/test/java/org/tron/core/db/TransactionTraceTest.java @@ -25,7 +25,7 @@ import org.junit.Test; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.tron.common.application.TronApplicationContext; -import org.tron.common.runtime.TVMTestUtils; +import org.tron.common.runtime.TvmTestUtils; import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; import org.tron.core.Wallet; @@ -107,7 +107,7 @@ public void testUseFee() String contractName = "tracetestContract"; String code = "608060405234801561001057600080fd5b5060005b6103e8811015610037576000818152602081905260409020819055600a01610014565b5061010f806100476000396000f30060806040526004361060525763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416634903b0d181146057578063da31158814607e578063fe4ba936146093575b600080fd5b348015606257600080fd5b50606c60043560ad565b60408051918252519081900360200190f35b348015608957600080fd5b50606c60043560bf565b348015609e57600080fd5b5060ab60043560243560d1565b005b60006020819052908152604090205481565b60009081526020819052604090205490565b600091825260208290526040909120555600a165627a7a723058200596e6c0a5371c2c533eb97ba4c1c19b0521750a5624cb5d2e93249c8b7219d20029"; String abi = "[{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"balances\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"account\",\"type\":\"uint256\"}],\"name\":\"getCoin\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"receiver\",\"type\":\"uint256\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"setCoin\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}]"; - CreateSmartContract smartContract = TVMTestUtils.createSmartContract( + CreateSmartContract smartContract = TvmTestUtils.createSmartContract( Wallet.decodeFromBase58Check(OwnerAddress), contractName, abi, code, 0, 100); Transaction transaction = Transaction.newBuilder().setRawData(raw.newBuilder().addContract( Contract.newBuilder().setParameter(Any.pack(smartContract)) @@ -130,7 +130,7 @@ public void testUseUsage() String contractName = "tracetestContract"; String code = "608060405234801561001057600080fd5b5060005b6103e8811015610037576000818152602081905260409020819055600a01610014565b5061010f806100476000396000f30060806040526004361060525763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416634903b0d181146057578063da31158814607e578063fe4ba936146093575b600080fd5b348015606257600080fd5b50606c60043560ad565b60408051918252519081900360200190f35b348015608957600080fd5b50606c60043560bf565b348015609e57600080fd5b5060ab60043560243560d1565b005b60006020819052908152604090205481565b60009081526020819052604090205490565b600091825260208290526040909120555600a165627a7a723058200596e6c0a5371c2c533eb97ba4c1c19b0521750a5624cb5d2e93249c8b7219d20029"; String abi = "[{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"balances\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"account\",\"type\":\"uint256\"}],\"name\":\"getCoin\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"receiver\",\"type\":\"uint256\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"setCoin\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}]"; - CreateSmartContract smartContract = TVMTestUtils.createSmartContract( + CreateSmartContract smartContract = TvmTestUtils.createSmartContract( Wallet.decodeFromBase58Check(OwnerAddress), contractName, abi, code, 0, 100); Transaction transaction = Transaction.newBuilder().setRawData(raw.newBuilder().addContract( Contract.newBuilder().setParameter(Any.pack(smartContract)) @@ -160,7 +160,7 @@ public void testTriggerUseFee() String contractName = "tracetestContract"; String code = "608060405234801561001057600080fd5b5060005b6103e8811015610037576000818152602081905260409020819055600a01610014565b5061010f806100476000396000f30060806040526004361060525763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416634903b0d181146057578063da31158814607e578063fe4ba936146093575b600080fd5b348015606257600080fd5b50606c60043560ad565b60408051918252519081900360200190f35b348015608957600080fd5b50606c60043560bf565b348015609e57600080fd5b5060ab60043560243560d1565b005b60006020819052908152604090205481565b60009081526020819052604090205490565b600091825260208290526040909120555600a165627a7a723058200596e6c0a5371c2c533eb97ba4c1c19b0521750a5624cb5d2e93249c8b7219d20029"; String abi = "[{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"balances\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"account\",\"type\":\"uint256\"}],\"name\":\"getCoin\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"receiver\",\"type\":\"uint256\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"setCoin\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}]"; - CreateSmartContract smartContract = TVMTestUtils.createSmartContract( + CreateSmartContract smartContract = TvmTestUtils.createSmartContract( Wallet.decodeFromBase58Check(OwnerAddress), contractName, abi, code, 0, 100); Transaction transaction = Transaction.newBuilder().setRawData(raw.newBuilder().addContract( Contract.newBuilder().setParameter(Any.pack(smartContract)) @@ -180,7 +180,7 @@ public void testTriggerUseFee() .put(Wallet.decodeFromBase58Check(TriggerOwnerAddress), ownerCapsule); dbManager.getAccountStore() .put(Wallet.decodeFromBase58Check(TriggerOwnerAddress), originCapsule); - TriggerSmartContract triggerContract = TVMTestUtils.createTriggerContract(contractAddress, + TriggerSmartContract triggerContract = TvmTestUtils.createTriggerContract(contractAddress, "setCoin(uint256,uint256)", "133,133", false, 0, Wallet.decodeFromBase58Check(TriggerOwnerAddress)); Transaction transaction2 = Transaction.newBuilder().setRawData(raw.newBuilder().addContract( @@ -206,7 +206,7 @@ public void testTriggerUseUsage() String contractName = "tracetestContract"; String code = "608060405234801561001057600080fd5b5060005b6103e8811015610037576000818152602081905260409020819055600a01610014565b5061010f806100476000396000f30060806040526004361060525763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416634903b0d181146057578063da31158814607e578063fe4ba936146093575b600080fd5b348015606257600080fd5b50606c60043560ad565b60408051918252519081900360200190f35b348015608957600080fd5b50606c60043560bf565b348015609e57600080fd5b5060ab60043560243560d1565b005b60006020819052908152604090205481565b60009081526020819052604090205490565b600091825260208290526040909120555600a165627a7a723058200596e6c0a5371c2c533eb97ba4c1c19b0521750a5624cb5d2e93249c8b7219d20029"; String abi = "[{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"balances\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"account\",\"type\":\"uint256\"}],\"name\":\"getCoin\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"receiver\",\"type\":\"uint256\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"setCoin\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}]"; - CreateSmartContract smartContract = TVMTestUtils.createSmartContract( + CreateSmartContract smartContract = TvmTestUtils.createSmartContract( Wallet.decodeFromBase58Check(OwnerAddress), contractName, abi, code, 0, 100); Transaction transaction = Transaction.newBuilder().setRawData(raw.newBuilder().addContract( Contract.newBuilder().setParameter(Any.pack(smartContract)) @@ -223,7 +223,7 @@ public void testTriggerUseUsage() accountCapsule.setFrozenForEnergy(10_000_000L, 0L); dbManager.getAccountStore() .put(Wallet.decodeFromBase58Check(TriggerOwnerAddress), accountCapsule); - TriggerSmartContract triggerContract = TVMTestUtils.createTriggerContract(contractAddress, + TriggerSmartContract triggerContract = TvmTestUtils.createTriggerContract(contractAddress, "setCoin(uint256,uint256)", "133,133", false, 0, Wallet.decodeFromBase58Check(TriggerOwnerAddress)); Transaction transaction2 = Transaction.newBuilder().setRawData(raw.newBuilder().addContract( diff --git a/src/test/java/org/tron/core/net/BaseNet.java b/src/test/java/org/tron/core/net/BaseNet.java index 0de3a9e6ac1..33676a8f51e 100644 --- a/src/test/java/org/tron/core/net/BaseNet.java +++ b/src/test/java/org/tron/core/net/BaseNet.java @@ -113,6 +113,7 @@ public void destroy() { for (PeerConnection peer : peerConnections) { peer.close(); } + context.destroy(); FileUtil.deleteDir(new File(dbPath)); } diff --git a/src/test/java/org/tron/core/net/DisconnectMessageTest.java b/src/test/java/org/tron/core/net/DisconnectMessageTest.java new file mode 100644 index 00000000000..82fe702af3d --- /dev/null +++ b/src/test/java/org/tron/core/net/DisconnectMessageTest.java @@ -0,0 +1,209 @@ +package org.tron.core.net; + +import com.google.protobuf.Message; +import com.google.protobuf.Message.Builder; +import org.tron.protos.Protocol; +import org.tron.protos.Protocol.DisconnectMessageOrBuilder; + +public class DisconnectMessageTest extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:protocol.DisconnectMessage) + DisconnectMessageOrBuilder { + + private static final long serialVersionUID = 0L; + + // Use DisconnectMessage.newBuilder() to construct. + private DisconnectMessageTest(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + + public DisconnectMessageTest() { + reason_ = 4; + name_ = 2; + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + + private DisconnectMessageTest( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + done = true; + break; + } + case 8: { + int rawValue = input.readEnum(); + + reason_ = rawValue; + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return null; + } + + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return null; + } + + public static final int REASON_FIELD_NUMBER = 1; + public static final int NAME_FIELD_NUMBER = 2; + private int reason_; + private int name_; + + + /** + * .protocol.ReasonCode reason = 1; + */ + public int getReasonValue() { + return reason_; + } + + public int getNameValue() {return name_;} + + /** + * .protocol.ReasonCode reason = 1; + */ + public org.tron.protos.Protocol.ReasonCode getReason() { + org.tron.protos.Protocol.ReasonCode result = org.tron.protos.Protocol.ReasonCode + .valueOf(reason_); + return result == null ? org.tron.protos.Protocol.ReasonCode.UNRECOGNIZED : result; + } + + public org.tron.protos.Protocol.ReasonCode getName() { + org.tron.protos.Protocol.ReasonCode result = org.tron.protos.Protocol.ReasonCode + .valueOf(name_); + return result == null ? org.tron.protos.Protocol.ReasonCode.UNRECOGNIZED : result; + } + + private byte memoizedIsInitialized = -1; + + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) { + return true; + } + if (isInitialized == 0) { + return false; + } + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (reason_ != org.tron.protos.Protocol.ReasonCode.REQUESTED.getNumber()) { + output.writeEnum(1, reason_); + } + if (name_ != org.tron.protos.Protocol.ReasonCode.REQUESTED.getNumber()) { + output.writeEnum(2, name_); + } + unknownFields.writeTo(output); + } + + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) { + return size; + } + + size = 0; + if (reason_ != org.tron.protos.Protocol.ReasonCode.REQUESTED.getNumber()) { + size += com.google.protobuf.CodedOutputStream + .computeEnumSize(1, reason_); + } + if (name_ != org.tron.protos.Protocol.ReasonCode.REQUESTED.getNumber()) { + size += com.google.protobuf.CodedOutputStream + .computeEnumSize(1, name_); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @Override + protected Message.Builder newBuilderForType(BuilderParent builderParent) { + return null; + } + + @Override + public Message.Builder newBuilderForType() { + return null; + } + + @Override + public Message.Builder toBuilder() { + return null; + } + + + // @@protoc_insertion_point(class_scope:protocol.DisconnectMessage) + private static final DisconnectMessageTest DEFAULT_INSTANCE; + + static { + DEFAULT_INSTANCE = new DisconnectMessageTest(); + } + + public static DisconnectMessageTest getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + public DisconnectMessageTest parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new DisconnectMessageTest(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + public DisconnectMessageTest getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} diff --git a/src/test/java/org/tron/core/net/MessageTest.java b/src/test/java/org/tron/core/net/MessageTest.java new file mode 100644 index 00000000000..978c0470d23 --- /dev/null +++ b/src/test/java/org/tron/core/net/MessageTest.java @@ -0,0 +1,40 @@ +package org.tron.core.net; + +import org.junit.Assert; +import org.junit.Test; +import org.tron.common.overlay.message.DisconnectMessage; +import org.tron.common.overlay.message.PingMessage; +import org.tron.common.utils.ReflectUtils; +import org.tron.core.exception.P2pException; +import org.tron.core.net.message.MessageTypes; +import org.tron.protos.Protocol.ReasonCode; + +public class MessageTest { + + private DisconnectMessage disconnectMessage; + + @Test + public void test1() throws Exception { + byte[] bytes = new DisconnectMessage(ReasonCode.TOO_MANY_PEERS).getData(); + DisconnectMessageTest disconnectMessageTest = new DisconnectMessageTest(); + try { + disconnectMessage = new DisconnectMessage(MessageTypes.P2P_DISCONNECT.asByte(), + disconnectMessageTest.toByteArray()); + } catch (Exception e) { + System.out.println(e.getMessage()); + Assert.assertTrue(e instanceof P2pException); + } + } + + public void test2() throws Exception { + DisconnectMessageTest disconnectMessageTest = new DisconnectMessageTest(); + long startTime = System.currentTimeMillis(); + for (int i = 0; i < 100000; i++) { + disconnectMessage = new DisconnectMessage(MessageTypes.P2P_DISCONNECT.asByte(), + disconnectMessageTest.toByteArray()); + } + long endTime = System.currentTimeMillis(); + System.out.println("spend time : " + (endTime - startTime)); + } + +} diff --git a/src/test/java/org/tron/core/net/UdpTest.java b/src/test/java/org/tron/core/net/UdpTest.java index 333d68f08e0..3ed04b80b4a 100644 --- a/src/test/java/org/tron/core/net/UdpTest.java +++ b/src/test/java/org/tron/core/net/UdpTest.java @@ -1,39 +1,31 @@ package org.tron.core.net; -import java.io.File; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.util.Arrays; +import java.util.List; import lombok.extern.slf4j.Slf4j; -import org.junit.After; import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.springframework.context.ApplicationContext; -import org.tron.common.application.TronApplicationContext; import org.testng.collections.Lists; -import org.tron.common.net.udp.message.discover.FindNodeMessage; +import org.tron.common.application.TronApplicationContext; import org.tron.common.net.udp.message.Message; +import org.tron.common.net.udp.message.discover.FindNodeMessage; import org.tron.common.net.udp.message.discover.NeighborsMessage; import org.tron.common.net.udp.message.discover.PingMessage; import org.tron.common.net.udp.message.discover.PongMessage; +import org.tron.common.overlay.discover.RefreshTask; import org.tron.common.overlay.discover.node.Node; import org.tron.common.overlay.discover.node.NodeManager; -import org.tron.common.overlay.discover.RefreshTask; -import org.tron.common.utils.FileUtil; -import org.tron.core.config.DefaultConfig; import org.tron.core.config.args.Args; -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.InetAddress; -import java.util.Arrays; -import java.util.List; - @Slf4j public class UdpTest { private NodeManager nodeManager; private int port = Args.getInstance().getNodeListenPort(); - private volatile boolean finishFlag = false; - private long timeOut = 30_000; +// private volatile boolean finishFlag = false; +// private long timeOut = 30_000; public UdpTest(TronApplicationContext context) { nodeManager = context.getBean(NodeManager.class); @@ -74,27 +66,14 @@ public void discover() throws Exception { Assert.assertTrue(nodeManager.getTable().getAllNodes().isEmpty()); PingMessage pingMessage = new PingMessage(from, nodeManager.getPublicHomeNode()); - - PongMessage pongMessage = new PongMessage(from); - - FindNodeMessage findNodeMessage = new FindNodeMessage(from, RefreshTask.getNodeId()); - - List peers = Lists.newArrayList(peer1, peer2); - NeighborsMessage neighborsMessage = new NeighborsMessage(from, peers); - - DatagramSocket socket = new DatagramSocket(); - DatagramPacket pingPacket = new DatagramPacket(pingMessage.getSendData(), pingMessage.getSendData().length, server, port); - DatagramPacket pongPacket = new DatagramPacket(pongMessage.getSendData(), - pongMessage.getSendData().length, server, port); - + FindNodeMessage findNodeMessage = new FindNodeMessage(from, RefreshTask.getNodeId()); DatagramPacket findNodePacket = new DatagramPacket(findNodeMessage.getSendData(), findNodeMessage.getSendData().length, server, port); - DatagramPacket neighborsPacket = new DatagramPacket(neighborsMessage.getSendData(), - neighborsMessage.getSendData().length, server, port); + DatagramSocket socket = new DatagramSocket(); // send ping msg socket.send(pingPacket); @@ -115,6 +94,9 @@ public void discover() throws Exception { pingFlag = true; Assert.assertTrue(msg instanceof PingMessage); Assert.assertTrue(Arrays.equals(((PingMessage) msg).getTo().getId(), from.getId())); + PongMessage pongMessage = new PongMessage(from, msg.getTimestamp()); + DatagramPacket pongPacket = new DatagramPacket(pongMessage.getSendData(), + pongMessage.getSendData().length, server, port); socket.send(pongPacket); } else if (!pongFlag) { pongFlag = true; @@ -122,6 +104,10 @@ public void discover() throws Exception { } else if (!findNodeFlag) { findNodeFlag = true; Assert.assertTrue(msg instanceof FindNodeMessage); + List peers = Lists.newArrayList(peer1, peer2); + NeighborsMessage neighborsMessage = new NeighborsMessage(from, peers, msg.getTimestamp()); + DatagramPacket neighborsPacket = new DatagramPacket(neighborsMessage.getSendData(), + neighborsMessage.getSendData().length, server, port); socket.send(neighborsPacket); socket.send(findNodePacket); } else if (!neighborsFlag) { @@ -136,7 +122,7 @@ public void discover() throws Exception { socket.close(); - finishFlag = true; +// finishFlag = true; } } diff --git a/src/test/java/org/tron/core/net/services/AdvServiceTest.java b/src/test/java/org/tron/core/net/services/AdvServiceTest.java index 2f78551e454..a1f37b8bd6e 100644 --- a/src/test/java/org/tron/core/net/services/AdvServiceTest.java +++ b/src/test/java/org/tron/core/net/services/AdvServiceTest.java @@ -1,6 +1,7 @@ package org.tron.core.net.services; import org.junit.Assert; +import org.junit.Ignore; import org.junit.Test; import org.tron.common.utils.Sha256Hash; import org.tron.core.capsule.BlockCapsule; @@ -9,6 +10,7 @@ import org.tron.core.net.service.AdvService; import org.tron.protos.Protocol.Inventory.InventoryType; +@Ignore public class AdvServiceTest { AdvService service = new AdvService(); diff --git a/src/test/java/org/tron/core/tire/TrieTest.java b/src/test/java/org/tron/core/tire/TrieTest.java new file mode 100644 index 00000000000..897bbc66761 --- /dev/null +++ b/src/test/java/org/tron/core/tire/TrieTest.java @@ -0,0 +1,153 @@ +/* + * Copyright (c) [2016] [ ] + * This file is part of the ethereumJ library. + * + * The ethereumJ library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The ethereumJ library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the ethereumJ library. If not, see . + */ +package org.tron.core.tire; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import org.junit.Assert; +import org.junit.Test; +import org.spongycastle.util.Arrays; +import org.tron.core.capsule.utils.RLP; +import org.tron.core.trie.TrieImpl; +import org.tron.core.trie.TrieImpl.Node; + +public class TrieTest { + + private static String c = "c"; + private static String ca = "ca"; + private static String cat = "cat"; + private static String dog = "dog"; + private static String doge = "doge"; + private static String test = "test"; + private static String dude = "dude"; + + @Test + public void test() { + TrieImpl trie = new TrieImpl(); + trie.put(new byte[]{1}, c.getBytes()); + Assert.assertTrue(Arrays.areEqual(trie.get(RLP.encodeInt(1)), c.getBytes())); + trie.put(new byte[]{1, 0}, ca.getBytes()); + trie.put(new byte[]{1, 1}, cat.getBytes()); + trie.put(new byte[]{1, 2}, dog.getBytes()); + trie.put(RLP.encodeInt(5), doge.getBytes()); + trie.put(RLP.encodeInt(6), doge.getBytes()); + trie.put(RLP.encodeInt(7), doge.getBytes()); + trie.put(RLP.encodeInt(11), doge.getBytes()); + trie.put(RLP.encodeInt(12), dude.getBytes()); + trie.put(RLP.encodeInt(13), test.getBytes()); + trie.delete(RLP.encodeInt(3)); + byte[] rootHash = trie.getRootHash(); + TrieImpl trieCopy = new TrieImpl(trie.getCache(), rootHash); + Assert.assertNull(trie.prove(RLP.encodeInt(111))); + Map map = trieCopy.prove(new byte[]{1, 1}); + boolean result = trie + .verifyProof(trieCopy.getRootHash(), new byte[]{1, 1}, (LinkedHashMap) map); + Assert.assertTrue(result); + System.out.println(trieCopy.prove(RLP.encodeInt(5))); + System.out.println(trieCopy.prove(RLP.encodeInt(6))); + assertTrue(RLP.encodeInt(5), trieCopy); + assertTrue(RLP.encodeInt(5), RLP.encodeInt(6), trieCopy); + assertTrue(RLP.encodeInt(6), trieCopy); + assertTrue(RLP.encodeInt(6), RLP.encodeInt(5), trieCopy); + // + trie.put(RLP.encodeInt(5), doge.getBytes()); + byte[] rootHash2 = trie.getRootHash(); + Assert.assertFalse(Arrays.areEqual(rootHash, rootHash2)); + trieCopy = new TrieImpl(trie.getCache(), rootHash2); + // + assertTrue(RLP.encodeInt(5), trieCopy); + assertFalse(RLP.encodeInt(5), RLP.encodeInt(6), trieCopy); + assertTrue(RLP.encodeInt(6), trieCopy); + assertFalse(RLP.encodeInt(6), RLP.encodeInt(5), trieCopy); + } + + @Test + public void test1() { + TrieImpl trie = new TrieImpl(); + int n = 100; + for (int i = 1; i < n; i++) { + trie.put(RLP.encodeInt(i), String.valueOf(i).getBytes()); + } + byte[] rootHash1 = trie.getRootHash(); + + TrieImpl trie2 = new TrieImpl(); + for (int i = 1; i < n; i++) { + trie2.put(RLP.encodeInt(i), String.valueOf(i).getBytes()); + } + byte[] rootHash2 = trie2.getRootHash(); + Assert.assertTrue(Arrays.areEqual(rootHash1, rootHash2)); + } + + @Test + public void test2() { + TrieImpl trie = new TrieImpl(); + int n = 100; + for (int i = 1; i < n; i++) { + trie.put(RLP.encodeInt(i), String.valueOf(i).getBytes()); + } + byte[] rootHash = trie.getRootHash(); + TrieImpl trieCopy = new TrieImpl(trie.getCache(), rootHash); + for (int i = 1; i < n; i++) { + assertTrue(RLP.encodeInt(i), trieCopy); + } + for (int i = 1; i < n; i++) { + for (int j = 1; j < n; j++) { + if (i != j) { + assertFalse(RLP.encodeInt(i), RLP.encodeInt(j), trieCopy); + } + } + } + } + + @Test + public void testOrder() { + TrieImpl trie = new TrieImpl(); + int n = 100; + List value = new ArrayList<>(); + for (int i = 1; i < n; i++) { + value.add(i); + trie.put(RLP.encodeInt(i), String.valueOf(i).getBytes()); + } + trie.put(RLP.encodeInt(10), String.valueOf(10).getBytes()); + value.add(10); + byte[] rootHash1 = trie.getRootHash(); + Collections.shuffle(value); + TrieImpl trie2 = new TrieImpl(); + for (int i : value) { + trie2.put(RLP.encodeInt(i), String.valueOf(i).getBytes()); + } + byte[] rootHash2 = trie2.getRootHash(); + Assert.assertTrue(java.util.Arrays.equals(rootHash1, rootHash2)); + } + + private void assertTrue(byte[] key, TrieImpl trieCopy) { + Assert.assertTrue(trieCopy.verifyProof(trieCopy.getRootHash(), key, trieCopy.prove(key))); + } + + private void assertTrue(byte[] key1, byte[] key2, TrieImpl trieCopy) { + Assert.assertTrue(trieCopy.verifyProof(trieCopy.getRootHash(), key2, trieCopy.prove(key1))); + } + + private void assertFalse(byte[] key1, byte[] key2, TrieImpl trieCopy) { + Assert.assertFalse(trieCopy.verifyProof(trieCopy.getRootHash(), key2, trieCopy.prove(key1))); + } + +} diff --git a/src/test/java/stest/tron/wallet/account/WalletTestAccount003.java b/src/test/java/stest/tron/wallet/account/WalletTestAccount003.java index 202bb909a09..5c27bb462ac 100644 --- a/src/test/java/stest/tron/wallet/account/WalletTestAccount003.java +++ b/src/test/java/stest/tron/wallet/account/WalletTestAccount003.java @@ -94,35 +94,39 @@ public void beforeClass() { @Test public void test1CreateAccount() { - Account noCreateAccount = queryAccount(lowBalTest, blockingStubFull); + Account noCreateAccount = PublicMethed.queryAccount(lowBalTest, blockingStubFull); while (noCreateAccount.getBalance() != 0) { ecKey = new ECKey(Utils.getRandom()); lowBalAddress = ecKey.getAddress(); lowBalTest = ByteArray.toHexString(ecKey.getPrivKeyBytes()); - noCreateAccount = queryAccount(lowBalTest, blockingStubFull); + noCreateAccount = PublicMethed.queryAccount(lowBalTest, blockingStubFull); } Assert.assertTrue(sendCoin(lowBalAddress, 1L, fromAddress, testKey002)); - noCreateAccount = queryAccount(lowBalTest, blockingStubFull); + noCreateAccount = PublicMethed.queryAccount(lowBalTest, blockingStubFull); logger.info(Long.toString(noCreateAccount.getBalance())); Assert.assertTrue(noCreateAccount.getBalance() == 1); } @Test(enabled = true) public void test2UpdateAccount() { - Assert.assertFalse(updateAccount(lowBalAddress, - mostLongNamePlusOneChar.getBytes(), lowBalTest)); - //Assert.assertFalse(updateAccount(lowBalAddress, "".getBytes(), lowBalTest)); + Assert.assertFalse(PublicMethed.updateAccount(lowBalAddress, + mostLongNamePlusOneChar.getBytes(), lowBalTest, blockingStubFull)); + Assert.assertFalse(PublicMethed.updateAccount(lowBalAddress, "".getBytes(), lowBalTest, + blockingStubFull)); String mostLongName = getRandomStr(33); - Assert.assertTrue(updateAccount(lowBalAddress, mostLongName.getBytes(), lowBalTest)); + Assert.assertTrue(PublicMethed.updateAccount(lowBalAddress, mostLongName.getBytes(), lowBalTest, + blockingStubFull)); String firstUpdateName = getRandomStr(32); - Assert.assertFalse(updateAccount(lowBalAddress, firstUpdateName.getBytes(), lowBalTest)); + Assert.assertFalse(PublicMethed.updateAccount(lowBalAddress, firstUpdateName.getBytes(), + lowBalTest, blockingStubFull)); String secondUpdateName = getRandomStr(15); - Assert.assertFalse(updateAccount(lowBalAddress, secondUpdateName.getBytes(), lowBalTest)); + Assert.assertFalse(PublicMethed.updateAccount(lowBalAddress, secondUpdateName.getBytes(), + lowBalTest, blockingStubFull)); } @Test(enabled = true) public void test3NoBalanceCreateAssetIssue() { - Account lowaccount = queryAccount(lowBalTest, blockingStubFull); + Account lowaccount = PublicMethed.queryAccount(lowBalTest, blockingStubFull); if (lowaccount.getBalance() > 0) { Assert.assertTrue(sendCoin(toAddress, lowaccount.getBalance(), lowBalAddress, lowBalTest)); } @@ -148,7 +152,7 @@ public void test5NoBalanceCreateWitness() { @Test(enabled = true) public void test6NoFreezeBalanceToUnfreezeBalance() { //Unfreeze account failed when no freeze balance - Account noFreezeAccount = queryAccount(lowBalTest, blockingStubFull); + Account noFreezeAccount = PublicMethed.queryAccount(lowBalTest, blockingStubFull); if (noFreezeAccount.getFrozenCount() == 0) { Assert.assertFalse(unFreezeBalance(lowBalAddress, lowBalTest)); } else { @@ -292,34 +296,6 @@ public int compare(Object o1, Object o2) { } } - /** - * constructor. - */ - - public Account queryAccount(String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { - byte[] address; - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - if (ecKey == null) { - String pubKey = loadPubKey(); //04 PubKey[128] - if (StringUtils.isEmpty(pubKey)) { - logger.warn("Warning: QueryAccount failed, no wallet address !!"); - return null; - } - byte[] pubKeyAsc = pubKey.getBytes(); - byte[] pubKeyHex = Hex.decode(pubKeyAsc); - ecKey = ECKey.fromPublicOnly(pubKeyHex); - } - return grpcQueryAccount(ecKey.getAddress(), blockingStubFull); - } - - public static String loadPubKey() { char[] buf = new char[0x100]; return String.valueOf(buf, 32, 130); @@ -359,46 +335,6 @@ private Protocol.Transaction signTransaction(ECKey ecKey, Protocol.Transaction t return TransactionUtils.sign(transaction, ecKey); } - /** - * constructor. - */ - - public boolean updateAccount(byte[] addressBytes, byte[] accountNameBytes, String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - Contract.AccountUpdateContract.Builder builder = Contract.AccountUpdateContract.newBuilder(); - ByteString basAddreess = ByteString.copyFrom(addressBytes); - ByteString bsAccountName = ByteString.copyFrom(accountNameBytes); - - builder.setAccountName(bsAccountName); - builder.setOwnerAddress(basAddreess); - - Contract.AccountUpdateContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.updateAccount(contract); - - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("Please check!!! transaction == null"); - return false; - } - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info("Please check!!! response.getresult==false"); - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - logger.info(name); - return true; - } - } - /** * constructor. */ diff --git a/src/test/java/stest/tron/wallet/common/client/.DS_Store b/src/test/java/stest/tron/wallet/common/client/.DS_Store index 17106eadb3b..697523bca8c 100644 Binary files a/src/test/java/stest/tron/wallet/common/client/.DS_Store and b/src/test/java/stest/tron/wallet/common/client/.DS_Store differ diff --git a/src/test/java/stest/tron/wallet/common/client/utils/AbiUtil.java b/src/test/java/stest/tron/wallet/common/client/utils/AbiUtil.java index dd0857dd2b6..6999a04d84a 100644 --- a/src/test/java/stest/tron/wallet/common/client/utils/AbiUtil.java +++ b/src/test/java/stest/tron/wallet/common/client/utils/AbiUtil.java @@ -6,34 +6,29 @@ import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.apache.commons.lang3.StringUtils; import org.spongycastle.util.encoders.Hex; import org.tron.common.crypto.Hash; +import org.tron.common.utils.ByteUtil; import org.tron.core.Wallet; public class AbiUtil { - static Pattern paramTypeBytes = Pattern.compile("^bytes([0-9]*)$"); - static Pattern paramTypeNumber = Pattern.compile("^(u?int)([0-9]*)$"); - static Pattern paramTypeArray = Pattern.compile("^(.*)\\[([0-9]*)\\]$"); - // + private static Pattern paramTypeBytes = Pattern.compile("^bytes([0-9]*)$"); + private static Pattern paramTypeNumber = Pattern.compile("^(u?int)([0-9]*)$"); + private static Pattern paramTypeArray = Pattern.compile("^(.*)\\[([0-9]*)]$"); - abstract static class Coder { + static abstract class Coder { boolean dynamic = false; - String name; - String type; - // DataWord[] encode + // DataWord[] encode abstract byte[] encode(String value); abstract byte[] decode(); } - /** - * constructor. - */ - public static String[] getTypes(String methodSign) { int start = methodSign.indexOf('(') + 1; int end = methodSign.indexOf(')'); @@ -43,15 +38,7 @@ public static String[] getTypes(String methodSign) { return typeString.split(","); } - public static String geMethodId(String methodSign) { - return null; - } - - /** - * constructor. - */ - - public static Coder getParamCoder(String type) { + private static Coder getParamCoder(String type) { switch (type) { case "address": @@ -64,8 +51,6 @@ public static Coder getParamCoder(String type) { return new CoderDynamicBytes(); case "trcToken": return new CoderNumber(); - default: - } if (paramTypeBytes.matcher(type).find()) { @@ -107,7 +92,7 @@ byte[] encode(String arrayValues) { Coder coder = getParamCoder(elementType); - List strings = null; + List strings; try { ObjectMapper mapper = new ObjectMapper(); strings = mapper.readValue(arrayValues, List.class); @@ -129,7 +114,7 @@ byte[] encode(String arrayValues) { } if (this.length == -1) { - return concat(new DataWord(strings.size()).getData(), pack(coders, strings)); + return ByteUtil.merge(new DataWord(strings.size()).getData(), pack(coders, strings)); } else { return pack(coders, strings); } @@ -184,20 +169,6 @@ byte[] decode() { } } - static class CoderToken extends Coder { - - @Override - byte[] encode(String value) { - String hex = Hex.toHexString(new DataWord(value.getBytes()).getData()); - return new CoderFixedBytes().encode(hex); - } - - @Override - byte[] decode() { - return new byte[0]; - } - } - static class CoderDynamicBytes extends Coder { CoderDynamicBytes() { @@ -206,7 +177,7 @@ static class CoderDynamicBytes extends Coder { @Override byte[] encode(String value) { - return encodeDynamicBytes(value); + return encodeDynamicBytes(value, true); } @Override @@ -238,6 +209,9 @@ static class CoderAddress extends Coder { @Override byte[] encode(String value) { byte[] address = Wallet.decodeFromBase58Check(value); + if (address == null) { + return null; + } return new DataWord(address).getData(); } @@ -264,18 +238,26 @@ byte[] decode() { } } - /** - * constructor. - */ + private static byte[] encodeDynamicBytes(String value, boolean hex) { + byte[] data; + if (hex) { + if (value.startsWith("0x")) { + value = value.substring(2); + } + data = Hex.decode(value); + } else { + data = value.getBytes(); + } + return encodeDynamicBytes(data); + } - public static byte[] encodeDynamicBytes(String value) { - byte[] data = value.getBytes(); + private static byte[] encodeDynamicBytes(byte[] data) { List ret = new ArrayList<>(); ret.add(new DataWord(data.length)); int readInx = 0; - int len = value.getBytes().length; - while (readInx < value.getBytes().length) { + int len = data.length; + while (readInx < data.length) { byte[] wordData = new byte[32]; int readLen = len - readInx >= 32 ? 32 : (len - readInx); System.arraycopy(data, readInx, wordData, 0, readLen); @@ -295,9 +277,12 @@ public static byte[] encodeDynamicBytes(String value) { return retBytes; } - /** - * constructor. - */ + private static byte[] encodeDynamicBytes(String value) { + byte[] data = value.getBytes(); + List ret = new ArrayList<>(); + ret.add(new DataWord(data.length)); + return encodeDynamicBytes(data); + } public static byte[] pack(List codes, List values) { @@ -308,10 +293,21 @@ public static byte[] pack(List codes, List values) { for (int idx = 0; idx < codes.size(); idx++) { Coder coder = codes.get(idx); - String value = values.get(idx).toString(); - + Object parameter = values.get(idx); + String value; + if (parameter instanceof List) { + StringBuilder sb = new StringBuilder(); + for (Object item : (List) parameter) { + if (sb.length() != 0) { + sb.append(","); + } + sb.append("\"").append(item).append("\""); + } + value = "[" + sb.toString() + "]"; + } else { + value = parameter.toString(); + } byte[] encoded = coder.encode(value); - encodedList.add(encoded); if (coder.dynamic) { @@ -345,18 +341,10 @@ public static byte[] pack(List codes, List values) { return data; } - /** - * constructor. - */ - public static String parseMethod(String methodSign, String params) { return parseMethod(methodSign, params, false); } - /** - * constructor. - */ - public static String parseMethod(String methodSign, String input, boolean isHex) { byte[] selector = new byte[4]; System.arraycopy(Hash.sha3(methodSign.getBytes()), 0, selector, 0, 4); @@ -372,18 +360,15 @@ public static String parseMethod(String methodSign, String input, boolean isHex) return Hex.toHexString(selector) + Hex.toHexString(encodedParms); } - /** - * constructor. - */ - public static byte[] encodeInput(String methodSign, String input) { ObjectMapper mapper = new ObjectMapper(); input = "[" + input + "]"; - List items = null; + List items; try { items = mapper.readValue(input, List.class); } catch (IOException e) { e.printStackTrace(); + return null; } List coders = new ArrayList<>(); @@ -395,12 +380,28 @@ public static byte[] encodeInput(String methodSign, String input) { return pack(coders, items); } - /** - * constructor. - */ + public static String parseMethod(String methodSign, List parameters) { + String[] inputArr = new String[parameters.size()]; + int i = 0; + for (Object parameter : parameters) { + if (parameter instanceof List) { + StringBuilder sb = new StringBuilder(); + for (Object item : (List) parameter) { + if (sb.length() != 0) { + sb.append(","); + } + sb.append("\"").append(item).append("\""); + } + inputArr[i++] = "[" + sb.toString() + "]"; + } else { + inputArr[i++] = + (parameter instanceof String) ? ("\"" + parameter + "\"") : ("" + parameter); + } + } + return parseMethod(methodSign, StringUtils.join(inputArr, ',')); + } public static void main(String[] args) { - // String method = "test(address,string,int)"; String method = "test(string,int2,string)"; String params = "asdf,3123,adf"; @@ -414,47 +415,15 @@ public static void main(String[] args) { System.out.println("token:" + parseMethod(tokenMethod, tokenParams)); String method1 = "test(uint256,string,string,uint256[])"; - String expected1 = "db103cf3000000000000000000000000000000000000000000000000000000000000000500" - + "0000000000000000000000000000000000000000000000000000000000008000000000000000000000000000" - + "000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000" - + "0000000000010000000000000000000000000000000000000000000000000000000000000000014200000000" - + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000014300000000000000000000000000000000000000000000000000000000" - + "0000000000000000000000000000000000000000000000000000000000000000000003000000000000000000" - + "0000000000000000000000000000000000000000000001000000000000000000000000000000000000000000" - + "00000000000000000000020000000000000000000000000000000000000000000000000000000000000003"; + String expected1 = "db103cf30000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000014200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000143000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003"; String method2 = "test(uint256,string,string,uint256[3])"; - String expected2 = "000000000000000000000000000000000000000000000000000000000000000100000000000" - + "0000000000000000000000000000000000000000000000000000200000000000000000000000000000000000" - + "00000000000000000000000000003"; + String expected2 = "000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003"; String listString = "1 ,\"B\",\"C\", [1, 2, 3]"; System.out.println(parseMethod(method1, listString)); System.out.println(parseMethod(method2, listString)); String bytesValue1 = "\"0112313\",112313"; - String bytesValue2 = "123123123"; System.out.println(parseMethod(byteMethod1, bytesValue1)); - - } - - /** - * constructor. - */ - - public static byte[] concat(byte[]... bytesArray) { - int length = 0; - for (byte[] bytes : bytesArray) { - length += bytes.length; - } - byte[] ret = new byte[length]; - int index = 0; - for (byte[] bytes : bytesArray) { - System.arraycopy(bytes, 0, ret, index, bytes.length); - index += bytes.length; - } - return ret; } - - } diff --git a/src/test/java/stest/tron/wallet/common/client/utils/HttpMethed.java b/src/test/java/stest/tron/wallet/common/client/utils/HttpMethed.java index 99d6051e33d..e998223a6c7 100644 --- a/src/test/java/stest/tron/wallet/common/client/utils/HttpMethed.java +++ b/src/test/java/stest/tron/wallet/common/client/utils/HttpMethed.java @@ -70,6 +70,34 @@ public static HttpResponse updateAccount(String httpNode, byte[] updateAccountAd return response; } + /** + * constructor. + */ + public static HttpResponse setAccountId(String httpNode, byte[] setAccountIdAddress, + String accountId, Boolean visable, String fromKey) { + try { + final String requestUrl = "http://" + httpNode + "/wallet/setaccountid"; + JsonObject userBaseObj2 = new JsonObject(); + userBaseObj2.addProperty("account_id", accountId); + userBaseObj2.addProperty("owner_address", + Base58.encode58Check(PublicMethed.getFinalAddress(fromKey))); + userBaseObj2.addProperty("visible",visable); + response = createConnect(requestUrl, userBaseObj2); + transactionString = EntityUtils.toString(response.getEntity()); + transactionSignString = gettransactionsign(httpNode, transactionString, fromKey); + logger.info(transactionString); + logger.info(transactionSignString); + response = broadcastTransaction(httpNode, transactionSignString); + } catch (Exception e) { + e.printStackTrace(); + httppost.releaseConnection(); + return null; + } + return response; + } + + + /** * constructor. */ @@ -213,13 +241,14 @@ public static HttpResponse sendCoin(String httpNode, byte[] fromAddress, byte[] * constructor. */ public static HttpResponse sendCoin(String httpNode, byte[] fromAddress, byte[] toAddress, - Long amount, String[] managerKeys) { + Long amount, Integer permissionId,String[] managerKeys) { try { final String requestUrl = "http://" + httpNode + "/wallet/createtransaction"; JsonObject userBaseObj2 = new JsonObject(); userBaseObj2.addProperty("to_address", ByteArray.toHexString(toAddress)); userBaseObj2.addProperty("owner_address", ByteArray.toHexString(fromAddress)); userBaseObj2.addProperty("amount", amount); + userBaseObj2.addProperty("Permission_id",permissionId); response = createConnect(requestUrl, userBaseObj2); transactionSignString = EntityUtils.toString(response.getEntity()); HttpResponse getSignWeightResponse; @@ -601,6 +630,8 @@ public static String deployContractGetTxid(String httpNode, String name, String userBaseObj2.addProperty("token_id", tokenId); userBaseObj2.addProperty("call_token_value", tokenValue); userBaseObj2.addProperty("owner_address", ByteArray.toHexString(ownerAddress)); + + logger.info(userBaseObj2.toString()); response = createConnect(requestUrl, userBaseObj2); transactionString = EntityUtils.toString(response.getEntity()); @@ -617,6 +648,46 @@ public static String deployContractGetTxid(String httpNode, String name, String return responseContent.getString("txID"); } + /** + * constructor. + */ + public static HttpResponse deployContractGetTxidWithTooBigLong(String httpNode, String name, + String abi, String bytecode, Long bandwidthLimit, Long feeLimit, + Integer consumeUserResourcePercent, Long originEnergyLimit, Long callValue, Integer tokenId, + Long tokenValue, byte[] ownerAddress, String fromKey) { + try { + final String requestUrl = "http://" + httpNode + "/wallet/deploycontract"; + + String text = "{\"call_token_value\": 10000000e100000000}"; + JSONObject jsonObject = JSONObject.parseObject(text); + logger.info("jsonObject: " + jsonObject.toString()); + jsonObject.put("name", name); + jsonObject.put("abi", abi); + jsonObject.put("bytecode", bytecode); + jsonObject.put("bandwidth_limit", bandwidthLimit); + jsonObject.put("fee_limit", feeLimit); + jsonObject.put("consume_user_resource_percent", consumeUserResourcePercent); + jsonObject.put("origin_energy_limit", originEnergyLimit); + jsonObject.put("call_value", callValue); + jsonObject.put("token_id", tokenId); + jsonObject.put("owner_address", ByteArray.toHexString(ownerAddress)); + + logger.info(jsonObject.toString()); + response = createConnect1(requestUrl,jsonObject); + /* transactionString = EntityUtils.toString(response.getEntity()); + logger.info(transactionString); + transactionSignString = gettransactionsign(httpNode, transactionString, fromKey); + logger.info(transactionSignString); + response = broadcastTransaction(httpNode, transactionSignString);*/ + } catch (Exception e) { + e.printStackTrace(); + httppost.releaseConnection(); + return null; + } + return response; + } + + /** * constructor. @@ -652,6 +723,30 @@ public static String triggerContractGetTxid(String httpNode, byte[] ownerAddress return responseContent.getString("txID"); } + /** + * constructor. + */ + public static HttpResponse triggerConstantContract(String httpNode, byte[] ownerAddress, + String contractAddress,String functionSelector, String parameter, Long feeLimit, + String fromKey) { + try { + final String requestUrl = "http://" + httpNode + "/wallet/triggerconstantcontract"; + JsonObject userBaseObj2 = new JsonObject(); + + userBaseObj2.addProperty("owner_address", ByteArray.toHexString(ownerAddress)); + userBaseObj2.addProperty("contract_address", contractAddress); + userBaseObj2.addProperty("function_selector", functionSelector); + userBaseObj2.addProperty("parameter", parameter); + userBaseObj2.addProperty("fee_limit", feeLimit); + + response = createConnect(requestUrl, userBaseObj2); + } catch (Exception e) { + e.printStackTrace(); + httppost.releaseConnection(); + return null; + } + return response; + } /** * constructor. @@ -869,6 +964,44 @@ public static HttpResponse broadcastTransaction(String httpNode, String transact return response; } + /** + * constructor. + */ + public static HttpResponse getAccountById(String httpNode, String accountId, Boolean visable) { + try { + String requestUrl = "http://" + httpNode + "/wallet/getaccountbyid"; + JsonObject userBaseObj2 = new JsonObject(); + userBaseObj2.addProperty("account_id", accountId); + userBaseObj2.addProperty("visible",visable); + response = createConnect(requestUrl, userBaseObj2); + } catch (Exception e) { + e.printStackTrace(); + httppost.releaseConnection(); + return null; + } + return response; + } + + /** + * constructor. + */ + public static HttpResponse getAccountByIdFromSolidity(String httpSolidityNode, String accountId, + Boolean visable) { + try { + String requestUrl = "http://" + httpSolidityNode + "/walletsolidity/getaccountbyid"; + JsonObject userBaseObj2 = new JsonObject(); + userBaseObj2.addProperty("account_id", accountId); + userBaseObj2.addProperty("visible",visable); + response = createConnect(requestUrl, userBaseObj2); + } catch (Exception e) { + e.printStackTrace(); + httppost.releaseConnection(); + return null; + } + return response; + } + + /** * constructor. */ @@ -1598,6 +1731,27 @@ public static HttpResponse getBlockByLimitNext(String httpNode, Integer startNum return response; } + /** + * constructor. + */ + public static HttpResponse getBlockByLimitNextFromSolidity(String httpNode, Integer startNum, + Integer endNum) { + try { + String requestUrl = "http://" + httpNode + "/walletsolidity/getblockbylimitnext"; + JsonObject userBaseObj2 = new JsonObject(); + userBaseObj2.addProperty("startNum", startNum); + userBaseObj2.addProperty("endNum", endNum); + response = createConnect(requestUrl, userBaseObj2); + } catch (Exception e) { + e.printStackTrace(); + httppost.releaseConnection(); + return null; + } + return response; + } + + + /** * constructor. */ @@ -1615,6 +1769,25 @@ public static HttpResponse getBlockByLastNum(String httpNode, Integer num) { return response; } + /** + * constructor. + */ + public static HttpResponse getBlockByLastNumFromSolidity(String httpNode, Integer num) { + try { + String requestUrl = "http://" + httpNode + "/walletsolidity/getblockbylatestnum"; + JsonObject userBaseObj2 = new JsonObject(); + userBaseObj2.addProperty("num", num); + response = createConnect(requestUrl, userBaseObj2); + } catch (Exception e) { + e.printStackTrace(); + httppost.releaseConnection(); + return null; + } + return response; + } + + + /** * constructor. */ @@ -1632,6 +1805,25 @@ public static HttpResponse getBlockById(String httpNode, String blockId) { return response; } + /** + * constructor. + */ + public static HttpResponse getBlockByIdFromSolidity(String httpNode, String blockId) { + try { + String requestUrl = "http://" + httpNode + "/walletsolidity/getblockbyid"; + JsonObject userBaseObj2 = new JsonObject(); + userBaseObj2.addProperty("value", blockId); + response = createConnect(requestUrl, userBaseObj2); + } catch (Exception e) { + e.printStackTrace(); + httppost.releaseConnection(); + return null; + } + return response; + } + + + /** * constructor. */ @@ -1740,6 +1932,36 @@ public static HttpResponse createConnect(String url, JsonObject requestBody) { return response; } + /** + * constructor. + */ + public static HttpResponse createConnect1(String url, JSONObject requestBody) { + try { + httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, + connectionTimeout); + httpClient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, soTimeout); + httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, + connectionTimeout * 10000); + httpClient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, soTimeout * 10000); + httppost = new HttpPost(url); + httppost.setHeader("Content-type", "application/json; charset=utf-8"); + httppost.setHeader("Connection", "Close"); + if (requestBody != null) { + StringEntity entity = new StringEntity(requestBody.toString(), Charset.forName("UTF-8")); + entity.setContentEncoding("UTF-8"); + entity.setContentType("application/json"); + httppost.setEntity(entity); + } + response = httpClient.execute(httppost); + } catch (Exception e) { + e.printStackTrace(); + httppost.releaseConnection(); + return null; + } + return response; + } + + /** * constructor. diff --git a/src/test/java/stest/tron/wallet/common/client/utils/PublicMethed.java b/src/test/java/stest/tron/wallet/common/client/utils/PublicMethed.java index 3e7c2b5461d..1a6b8fac0b8 100644 --- a/src/test/java/stest/tron/wallet/common/client/utils/PublicMethed.java +++ b/src/test/java/stest/tron/wallet/common/client/utils/PublicMethed.java @@ -6,11 +6,20 @@ import com.google.gson.JsonElement; import com.google.gson.JsonParser; import com.google.protobuf.ByteString; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; import java.math.BigInteger; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -38,6 +47,7 @@ import org.tron.common.crypto.ECKey.ECDSASignature; import org.tron.common.crypto.Hash; import org.tron.common.utils.ByteArray; +import org.tron.common.utils.Utils; import org.tron.core.Wallet; import org.tron.keystore.WalletFile; import org.tron.protos.Contract; @@ -48,6 +58,7 @@ import org.tron.protos.Protocol; import org.tron.protos.Protocol.Account; import org.tron.protos.Protocol.Block; +//import org.tron.protos.Protocol.DeferredTransaction; import org.tron.protos.Protocol.DelegatedResourceAccountIndex; import org.tron.protos.Protocol.Exchange; import org.tron.protos.Protocol.Key; @@ -56,6 +67,7 @@ import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.Transaction.Result; import org.tron.protos.Protocol.TransactionInfo; +import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; import stest.tron.wallet.common.client.WalletClient; @@ -102,6 +114,61 @@ public static Boolean createAssetIssue(byte[] address, String name, Long totalSu builder.setUrl(ByteString.copyFrom(url.getBytes())); builder.setFreeAssetNetLimit(freeAssetNetLimit); builder.setPublicFreeAssetNetLimit(publicFreeAssetNetLimit); + Contract.AssetIssueContract.FrozenSupply.Builder frozenBuilder = Contract.AssetIssueContract + .FrozenSupply.newBuilder(); + frozenBuilder.setFrozenAmount(fronzenAmount); + frozenBuilder.setFrozenDays(frozenDay); + builder.addFrozenSupply(0, frozenBuilder); + + Protocol.Transaction transaction = blockingStubFull.createAssetIssue(builder.build()); + if (transaction == null || transaction.getRawData().getContractCount() == 0) { + logger.info("transaction == null"); + return false; + } + transaction = signTransaction(ecKey, transaction); + + GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); + + return response.getResult(); + } catch (Exception ex) { + ex.printStackTrace(); + return false; + } + } + + /** + * constructor. + */ + + public static Boolean createAssetIssue(byte[] address, String name, String abbreviation, + Long totalSupply, Integer trxNum, Integer icoNum, Long startTime, Long endTime, + Integer voteScore, String description, String url, Long freeAssetNetLimit, + Long publicFreeAssetNetLimit, Long fronzenAmount, Long frozenDay, String priKey, + WalletGrpc.WalletBlockingStub blockingStubFull) { + Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); + ECKey temKey = null; + try { + BigInteger priK = new BigInteger(priKey, 16); + temKey = ECKey.fromPrivate(priK); + } catch (Exception ex) { + ex.printStackTrace(); + } + ECKey ecKey = temKey; + try { + Contract.AssetIssueContract.Builder builder = Contract.AssetIssueContract.newBuilder(); + builder.setOwnerAddress(ByteString.copyFrom(address)); + builder.setName(ByteString.copyFrom(name.getBytes())); + builder.setAbbr(ByteString.copyFrom(abbreviation.getBytes())); + builder.setTotalSupply(totalSupply); + builder.setTrxNum(trxNum); + builder.setNum(icoNum); + builder.setStartTime(startTime); + builder.setEndTime(endTime); + builder.setVoteScore(voteScore); + builder.setDescription(ByteString.copyFrom(description.getBytes())); + builder.setUrl(ByteString.copyFrom(url.getBytes())); + builder.setFreeAssetNetLimit(freeAssetNetLimit); + builder.setPublicFreeAssetNetLimit(publicFreeAssetNetLimit); Contract.AssetIssueContract.FrozenSupply.Builder frozenBuilder = Contract.AssetIssueContract.FrozenSupply.newBuilder(); frozenBuilder.setFrozenAmount(fronzenAmount); @@ -286,9 +353,6 @@ public static Account queryAccount(byte[] address, WalletGrpc Account request = Account.newBuilder().setAddress(addressBs).build(); return blockingStubFull.getAccount(request); } - /** - * constructor. - */ /** * constructor. @@ -388,6 +452,8 @@ public static Protocol.Transaction signTransaction(ECKey ecKey, return null; } transaction = TransactionUtils.setTimestamp(transaction); + logger.info("Txid in sign is " + ByteArray.toHexString(Sha256Hash.hash(transaction + .getRawData().toByteArray()))); return TransactionUtils.sign(transaction, ecKey); } @@ -604,40 +670,501 @@ public static Return freezeBalance2(byte[] addRess, long freezeBalance, long fre System.out.println("Transaction is empty"); return transactionExtention.getResult(); } - System.out.println( - "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); - - transaction = TransactionUtils.setTimestamp(transaction); - transaction = TransactionUtils.sign(transaction, ecKey); + System.out.println( + "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); + + transaction = TransactionUtils.setTimestamp(transaction); + transaction = TransactionUtils.sign(transaction, ecKey); + GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); + + if (response.getResult() == false) { + return response; + } + + Long afterBlockNum = 0L; + + while (afterBlockNum < beforeBlockNum) { + Protocol.Block currentBlock1 = blockingStubFull.getNowBlock(GrpcAPI + .EmptyMessage.newBuilder().build()); + afterBlockNum = currentBlock1.getBlockHeader().getRawData().getNumber(); + } + + Protocol.Account afterFronzen = queryAccount(priKey, blockingStubFull); + Long afterFrozenBalance = afterFronzen.getFrozen(0).getFrozenBalance(); + logger.info(Long.toString(afterFronzen.getFrozen(0).getFrozenBalance())); + logger.info("beforefronen" + beforeFrozenBalance.toString() + " afterfronzen" + + afterFrozenBalance.toString()); + Assert.assertTrue(afterFrozenBalance - beforeFrozenBalance == freezeBalance); + return ret; + } + + /** + * constructor. + */ + + public static Boolean unFreezeBalance(byte[] address, String priKey, int resourceCode, + byte[] receiverAddress, WalletGrpc.WalletBlockingStub blockingStubFull) { + Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); + ECKey temKey = null; + try { + BigInteger priK = new BigInteger(priKey, 16); + temKey = ECKey.fromPrivate(priK); + } catch (Exception ex) { + ex.printStackTrace(); + } + final ECKey ecKey = temKey; + Contract.UnfreezeBalanceContract.Builder builder = Contract.UnfreezeBalanceContract + .newBuilder(); + ByteString byteAddreess = ByteString.copyFrom(address); + builder.setOwnerAddress(byteAddreess).setResourceValue(resourceCode); + if (receiverAddress != null) { + ByteString receiverAddressBytes = ByteString.copyFrom(receiverAddress); + builder.setReceiverAddress(receiverAddressBytes); + } + + Contract.UnfreezeBalanceContract contract = builder.build(); + Transaction transaction = blockingStubFull.unfreezeBalance(contract); + transaction = signTransaction(ecKey, transaction); + GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); + + return response.getResult(); + } + + /** + * constructor. + */ + + public static Boolean sendcoin(byte[] to, long amount, byte[] owner, String priKey, + WalletGrpc.WalletBlockingStub blockingStubFull) { + Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); + //String priKey = testKey002; + ECKey temKey = null; + try { + BigInteger priK = new BigInteger(priKey, 16); + temKey = ECKey.fromPrivate(priK); + } catch (Exception ex) { + ex.printStackTrace(); + } + final ECKey ecKey = temKey; + + Integer times = 0; + while (times++ <= 2) { + + Contract.TransferContract.Builder builder = Contract.TransferContract.newBuilder(); + ByteString bsTo = ByteString.copyFrom(to); + ByteString bsOwner = ByteString.copyFrom(owner); + builder.setToAddress(bsTo); + builder.setOwnerAddress(bsOwner); + builder.setAmount(amount); + + Contract.TransferContract contract = builder.build(); + Protocol.Transaction transaction = blockingStubFull.createTransaction(contract); + if (transaction == null || transaction.getRawData().getContractCount() == 0) { + logger.info("transaction ==null"); + continue; + } + transaction = signTransaction(ecKey, transaction); + GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); + return response.getResult(); + } + return false; + } + + /** + * constructor. + */ + + public static Boolean cancelDeferredTransactionById(String txid,byte[] owner,String priKey, + WalletGrpc.WalletBlockingStub blockingStubFull) { + Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); + ECKey temKey = null; + try { + BigInteger priK = new BigInteger(priKey, 16); + temKey = ECKey.fromPrivate(priK); + } catch (Exception ex) { + ex.printStackTrace(); + } + final ECKey ecKey = temKey; + /*Contract.CancelDeferredTransactionContract.Builder builder = Contract + .CancelDeferredTransactionContract.newBuilder(); + builder.setTransactionId(ByteString.copyFrom(ByteArray.fromHexString(txid))); + builder.setOwnerAddress(ByteString.copyFrom(owner)); + + Contract.CancelDeferredTransactionContract contract = builder.build(); + TransactionExtention transactionExtention = blockingStubFull + .createCancelDeferredTransactionContract(contract); + + if (transactionExtention == null) { + return false; + } + Return ret = transactionExtention.getResult(); + if (!ret.getResult()) { + System.out.println("Code = " + ret.getCode()); + System.out.println("Message = " + ret.getMessage().toStringUtf8()); + return false; + } + Transaction transaction = transactionExtention.getTransaction(); + if (transaction == null || transaction.getRawData().getContractCount() == 0) { + System.out.println("Transaction is empty"); + return false; + } + System.out.println( + "Cancel transaction before sign txid = " + ByteArray.toHexString( + transactionExtention.getTxid().toByteArray())); + + transaction = signTransaction(ecKey, transaction); + System.out.println( + "Cancel transaction txid = " + ByteArray.toHexString(transactionExtention + .getTxid().toByteArray())); + GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); + return response.getResult();*/ + return null; + } + + /** + * constructor. + */ + + public static String cancelDeferredTransactionByIdGetTxid(String txid,byte[] owner,String priKey, + WalletGrpc.WalletBlockingStub blockingStubFull) { + Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); + ECKey temKey = null; + try { + BigInteger priK = new BigInteger(priKey, 16); + temKey = ECKey.fromPrivate(priK); + } catch (Exception ex) { + ex.printStackTrace(); + } + final ECKey ecKey = temKey; + /* Contract.CancelDeferredTransactionContract.Builder builder = Contract + .CancelDeferredTransactionContract.newBuilder(); + builder.setTransactionId(ByteString.copyFrom(ByteArray.fromHexString(txid))); + builder.setOwnerAddress(ByteString.copyFrom(owner)); + + Contract.CancelDeferredTransactionContract contract = builder.build(); + TransactionExtention transactionExtention = blockingStubFull + .createCancelDeferredTransactionContract(contract); + + if (transactionExtention == null) { + return null; + } + Return ret = transactionExtention.getResult(); + if (!ret.getResult()) { + System.out.println("Code = " + ret.getCode()); + System.out.println("Message = " + ret.getMessage().toStringUtf8()); + return null; + } + Transaction transaction = transactionExtention.getTransaction(); + if (transaction == null || transaction.getRawData().getContractCount() == 0) { + System.out.println("Transaction is empty"); + return null; + } + System.out.println( + "Cancel transaction before sign txid = " + ByteArray.toHexString( + transactionExtention.getTxid().toByteArray())); + + transaction = signTransaction(ecKey, transaction); + System.out.println( + "Cancel transaction txid = " + ByteArray.toHexString(transactionExtention + .getTxid().toByteArray())); + GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); + + return ByteArray.toHexString(Sha256Hash.hash(transaction.getRawData().toByteArray()));*/ + return null; + } + + + + + + /** + * constructor. + */ + + public static Boolean sendcoinDelayed(byte[] to, long amount, long delaySeconds, byte[] owner, + String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { + Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); + ECKey temKey = null; + try { + BigInteger priK = new BigInteger(priKey, 16); + temKey = ECKey.fromPrivate(priK); + } catch (Exception ex) { + ex.printStackTrace(); + } + final ECKey ecKey = temKey; + + Contract.TransferContract.Builder builder = Contract.TransferContract.newBuilder(); + ByteString bsTo = ByteString.copyFrom(to); + ByteString bsOwner = ByteString.copyFrom(owner); + builder.setToAddress(bsTo); + builder.setOwnerAddress(bsOwner); + builder.setAmount(amount); + + Contract.TransferContract contract = builder.build(); + Protocol.Transaction transaction = blockingStubFull.createTransaction(contract); + + //transaction = TransactionUtils.setDelaySeconds(transaction, delaySeconds); + + if (transaction == null || transaction.getRawData().getContractCount() == 0) { + logger.info("transaction ==null"); + return false; + } + transaction = signTransaction(ecKey, transaction); + logger.info("Txid is " + ByteArray.toHexString(Sha256Hash.hash(transaction + .getRawData().toByteArray()))); + GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); + return response.getResult(); + } + + /** + * constructor. + */ + + public static boolean transferAssetDelay(byte[] to, byte[] assertName, long amount, + long delaySeconds, byte[] address, String priKey, + WalletGrpc.WalletBlockingStub blockingStubFull) { + Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); + ECKey temKey = null; + try { + BigInteger priK = new BigInteger(priKey, 16); + temKey = ECKey.fromPrivate(priK); + } catch (Exception ex) { + ex.printStackTrace(); + } + final ECKey ecKey = temKey; + + Contract.TransferAssetContract.Builder builder = Contract.TransferAssetContract.newBuilder(); + ByteString bsTo = ByteString.copyFrom(to); + ByteString bsName = ByteString.copyFrom(assertName); + ByteString bsOwner = ByteString.copyFrom(address); + builder.setToAddress(bsTo); + builder.setAssetName(bsName); + builder.setOwnerAddress(bsOwner); + builder.setAmount(amount); + + Contract.TransferAssetContract contract = builder.build(); + Protocol.Transaction transaction = blockingStubFull.transferAsset(contract); + //transaction = TransactionUtils.setDelaySeconds(transaction, delaySeconds); + + if (transaction == null || transaction.getRawData().getContractCount() == 0) { + if (transaction == null) { + logger.info("transaction == null"); + } else { + logger.info("transaction.getRawData().getContractCount() == 0"); + } + return false; + } + transaction = signTransaction(ecKey, transaction); + logger.info("Txid is " + ByteArray.toHexString(Sha256Hash.hash(transaction + .getRawData().toByteArray()))); + GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); + return response.getResult(); + } + + /** + * constructor. + */ + + public static String createAccountDelayGetTxid(byte[] ownerAddress, byte[] newAddress, + Long delaySeconds, String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { + Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); + ECKey temKey = null; + try { + BigInteger priK = new BigInteger(priKey, 16); + temKey = ECKey.fromPrivate(priK); + } catch (Exception ex) { + ex.printStackTrace(); + } + final ECKey ecKey = temKey; + + byte[] owner = ownerAddress; + Contract.AccountCreateContract.Builder builder = Contract.AccountCreateContract.newBuilder(); + builder.setOwnerAddress(ByteString.copyFrom(owner)); + builder.setAccountAddress(ByteString.copyFrom(newAddress)); + Contract.AccountCreateContract contract = builder.build(); + Transaction transaction = blockingStubFull.createAccount(contract); + //transaction = TransactionUtils.setDelaySeconds(transaction, delaySeconds); + if (transaction == null || transaction.getRawData().getContractCount() == 0) { + logger.info("transaction == null"); + } + transaction = signTransaction(ecKey, transaction); + logger.info("Txid is " + ByteArray.toHexString(Sha256Hash.hash(transaction + .getRawData().toByteArray()))); + GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); + return ByteArray.toHexString(Sha256Hash.hash(transaction.getRawData().toByteArray())); + + } + + /** + * constructor. + */ + + public static String updateAccountDelayGetTxid(byte[] addressBytes, byte[] accountNameBytes, + Long delaySeconds, String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { + Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); + ECKey temKey = null; + try { + BigInteger priK = new BigInteger(priKey, 16); + temKey = ECKey.fromPrivate(priK); + } catch (Exception ex) { + ex.printStackTrace(); + } + final ECKey ecKey = temKey; + + Contract.AccountUpdateContract.Builder builder = Contract.AccountUpdateContract.newBuilder(); + ByteString basAddreess = ByteString.copyFrom(addressBytes); + ByteString bsAccountName = ByteString.copyFrom(accountNameBytes); + + builder.setAccountName(bsAccountName); + builder.setOwnerAddress(basAddreess); + + Contract.AccountUpdateContract contract = builder.build(); + Protocol.Transaction transaction = blockingStubFull.updateAccount(contract); + //transaction = TransactionUtils.setDelaySeconds(transaction, delaySeconds); + if (transaction == null || transaction.getRawData().getContractCount() == 0) { + logger.info("Please check!!! transaction == null"); + return null; + } + transaction = signTransaction(ecKey, transaction); + logger.info("Txid is " + ByteArray.toHexString(Sha256Hash.hash(transaction + .getRawData().toByteArray()))); + GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); + return ByteArray.toHexString(Sha256Hash.hash(transaction.getRawData().toByteArray())); + } + + /** + * constructor. + */ + + public static String unfreezeAssetDelayGetTxid(byte[] address,Long delaySeconds, String priKey, + WalletGrpc.WalletBlockingStub blockingStubFull) { + Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); + ECKey temKey = null; + try { + BigInteger priK = new BigInteger(priKey, 16); + temKey = ECKey.fromPrivate(priK); + } catch (Exception ex) { + ex.printStackTrace(); + } + final ECKey ecKey = temKey; + + Contract.UnfreezeAssetContract.Builder builder = Contract.UnfreezeAssetContract + .newBuilder(); + ByteString byteAddreess = ByteString.copyFrom(address); + builder.setOwnerAddress(byteAddreess); + + Contract.UnfreezeAssetContract contract = builder.build(); + Protocol.Transaction transaction = blockingStubFull.unfreezeAsset(contract); + //transaction = TransactionUtils.setDelaySeconds(transaction, delaySeconds); + if (transaction == null || transaction.getRawData().getContractCount() == 0) { + logger.info("Please check!!! transaction == null"); + return null; + } + transaction = signTransaction(ecKey, transaction); + logger.info("Txid is " + ByteArray.toHexString(Sha256Hash.hash(transaction + .getRawData().toByteArray()))); + GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); + return ByteArray.toHexString(Sha256Hash.hash(transaction.getRawData().toByteArray())); + + + + + } + + + /** + * constructor. + */ + + public static String transferAssetDelayGetTxid(byte[] to, byte[] assertName, long amount, + long delaySeconds, byte[] address, String priKey, + WalletGrpc.WalletBlockingStub blockingStubFull) { + Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); + ECKey temKey = null; + try { + BigInteger priK = new BigInteger(priKey, 16); + temKey = ECKey.fromPrivate(priK); + } catch (Exception ex) { + ex.printStackTrace(); + } + final ECKey ecKey = temKey; + + Contract.TransferAssetContract.Builder builder = Contract.TransferAssetContract.newBuilder(); + ByteString bsTo = ByteString.copyFrom(to); + ByteString bsName = ByteString.copyFrom(assertName); + ByteString bsOwner = ByteString.copyFrom(address); + builder.setToAddress(bsTo); + builder.setAssetName(bsName); + builder.setOwnerAddress(bsOwner); + builder.setAmount(amount); + + Contract.TransferAssetContract contract = builder.build(); + Protocol.Transaction transaction = blockingStubFull.transferAsset(contract); + //transaction = TransactionUtils.setDelaySeconds(transaction, delaySeconds); + + if (transaction == null || transaction.getRawData().getContractCount() == 0) { + if (transaction == null) { + logger.info("transaction == null"); + } else { + logger.info("transaction.getRawData().getContractCount() == 0"); + } + return null; + } + transaction = signTransaction(ecKey, transaction); + logger.info("Txid is " + ByteArray.toHexString(Sha256Hash.hash(transaction + .getRawData().toByteArray()))); GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); + return ByteArray.toHexString(Sha256Hash.hash(transaction.getRawData().toByteArray())); + } - if (response.getResult() == false) { - return response; - } - Long afterBlockNum = 0L; - while (afterBlockNum < beforeBlockNum) { - Protocol.Block currentBlock1 = blockingStubFull.getNowBlock(GrpcAPI - .EmptyMessage.newBuilder().build()); - afterBlockNum = currentBlock1.getBlockHeader().getRawData().getNumber(); + /** + * constructor. + */ + + public static String sendcoinDelayedGetTxid(byte[] to, long amount, long delaySeconds, + byte[] owner, String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { + Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); + ECKey temKey = null; + try { + BigInteger priK = new BigInteger(priKey, 16); + temKey = ECKey.fromPrivate(priK); + } catch (Exception ex) { + ex.printStackTrace(); } + final ECKey ecKey = temKey; - Protocol.Account afterFronzen = queryAccount(priKey, blockingStubFull); - Long afterFrozenBalance = afterFronzen.getFrozen(0).getFrozenBalance(); - logger.info(Long.toString(afterFronzen.getFrozen(0).getFrozenBalance())); - logger.info("beforefronen" + beforeFrozenBalance.toString() + " afterfronzen" - + afterFrozenBalance.toString()); - Assert.assertTrue(afterFrozenBalance - beforeFrozenBalance == freezeBalance); - return ret; + Contract.TransferContract.Builder builder = Contract.TransferContract.newBuilder(); + ByteString bsTo = ByteString.copyFrom(to); + ByteString bsOwner = ByteString.copyFrom(owner); + builder.setToAddress(bsTo); + builder.setOwnerAddress(bsOwner); + builder.setAmount(amount); + + Contract.TransferContract contract = builder.build(); + Protocol.Transaction transaction = blockingStubFull.createTransaction(contract); + + //transaction = TransactionUtils.setDelaySeconds(transaction, delaySeconds); + + if (transaction == null || transaction.getRawData().getContractCount() == 0) { + logger.info("transaction ==null"); + return null; + } + transaction = signTransaction(ecKey, transaction); + logger.info("Txid is " + ByteArray.toHexString(Sha256Hash.hash(transaction + .getRawData().toByteArray()))); + GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); + return ByteArray.toHexString(Sha256Hash.hash(transaction.getRawData().toByteArray())); } /** * constructor. */ - public static Boolean unFreezeBalance(byte[] address, String priKey, int resourceCode, - byte[] receiverAddress, WalletGrpc.WalletBlockingStub blockingStubFull) { + public static String setAccountIdDelayGetTxid(byte[] accountIdBytes, long delaySeconds, + byte[] ownerAddress, String priKey, + WalletGrpc.WalletBlockingStub blockingStubFull) { Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); ECKey temKey = null; try { @@ -647,31 +1174,37 @@ public static Boolean unFreezeBalance(byte[] address, String priKey, int resourc ex.printStackTrace(); } final ECKey ecKey = temKey; - Contract.UnfreezeBalanceContract.Builder builder = Contract.UnfreezeBalanceContract - .newBuilder(); - ByteString byteAddreess = ByteString.copyFrom(address); - builder.setOwnerAddress(byteAddreess).setResourceValue(resourceCode); - if (receiverAddress != null) { - ByteString receiverAddressBytes = ByteString.copyFrom(receiverAddress); - builder.setReceiverAddress(receiverAddressBytes); - } - Contract.UnfreezeBalanceContract contract = builder.build(); - Transaction transaction = blockingStubFull.unfreezeBalance(contract); + byte[] owner = ownerAddress; + Contract.SetAccountIdContract.Builder builder = Contract.SetAccountIdContract.newBuilder(); + ByteString bsAddress = ByteString.copyFrom(owner); + ByteString bsAccountId = ByteString.copyFrom(accountIdBytes); + builder.setAccountId(bsAccountId); + builder.setOwnerAddress(bsAddress); + Contract.SetAccountIdContract contract = builder.build(); + Transaction transaction = blockingStubFull.setAccountId(contract); + //transaction = TransactionUtils.setDelaySeconds(transaction, delaySeconds); + + if (transaction == null || transaction.getRawData().getContractCount() == 0) { + logger.info("transaction == null"); + } transaction = signTransaction(ecKey, transaction); + logger.info("Txid is " + ByteArray.toHexString(Sha256Hash.hash(transaction + .getRawData().toByteArray()))); GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - - return response.getResult(); + return ByteArray.toHexString(Sha256Hash.hash(transaction.getRawData().toByteArray())); } + + /** * constructor. */ - public static Boolean sendcoin(byte[] to, long amount, byte[] owner, String priKey, + public static String updateAssetDelay(byte[] address, byte[] description, byte[] url, + long newLimit,long newPublicLimit, long delaySeconds, String priKey, WalletGrpc.WalletBlockingStub blockingStubFull) { Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); - //String priKey = testKey002; ECKey temKey = null; try { BigInteger priK = new BigInteger(priKey, 16); @@ -680,31 +1213,31 @@ public static Boolean sendcoin(byte[] to, long amount, byte[] owner, String priK ex.printStackTrace(); } final ECKey ecKey = temKey; + Contract.UpdateAssetContract.Builder builder = + Contract.UpdateAssetContract.newBuilder(); + ByteString basAddreess = ByteString.copyFrom(address); + builder.setDescription(ByteString.copyFrom(description)); + builder.setUrl(ByteString.copyFrom(url)); + builder.setNewLimit(newLimit); + builder.setNewPublicLimit(newPublicLimit); + builder.setOwnerAddress(basAddreess); - Integer times = 0; - while (times++ <= 2) { - - Contract.TransferContract.Builder builder = Contract.TransferContract.newBuilder(); - ByteString bsTo = ByteString.copyFrom(to); - ByteString bsOwner = ByteString.copyFrom(owner); - builder.setToAddress(bsTo); - builder.setOwnerAddress(bsOwner); - builder.setAmount(amount); - - Contract.TransferContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.createTransaction(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction ==null"); - continue; - } - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - return response.getResult(); + Contract.UpdateAssetContract contract + = builder.build(); + Protocol.Transaction transaction = blockingStubFull.updateAsset(contract); + //transaction = TransactionUtils.setDelaySeconds(transaction, delaySeconds); + if (transaction == null || transaction.getRawData().getContractCount() == 0) { + return null; } - return false; + transaction = signTransaction(ecKey, transaction); + logger.info("Txid is " + ByteArray.toHexString(Sha256Hash.hash(transaction + .getRawData().toByteArray()))); + GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); + return ByteArray.toHexString(Sha256Hash.hash(transaction.getRawData().toByteArray())); } + /** * constructor. */ @@ -819,6 +1352,7 @@ public static Optional getTransactionById(String txId, ByteString bsTxid = ByteString.copyFrom(ByteArray.fromHexString(txId)); BytesMessage request = BytesMessage.newBuilder().setValue(bsTxid).build(); Transaction transaction = blockingStubFull.getTransactionById(request); + return Optional.ofNullable(transaction); } @@ -834,6 +1368,41 @@ public static Optional getTransactionById(String txId, return Optional.ofNullable(transaction); } + /** + * constructor. + */ + public static Long getAssetBalanceByAssetId(ByteString assetId,String priKey, + WalletGrpc.WalletBlockingStub blockingStubFull) { + Account assetOwnerAccount = queryAccount(priKey, blockingStubFull); + Long assetOwnerAssetBalance = 0L; + for (String id : assetOwnerAccount.getAssetV2Map().keySet()) { + if (assetId.toStringUtf8().equalsIgnoreCase(id)) { + assetOwnerAssetBalance = assetOwnerAccount.getAssetV2Map().get(id); + } + } + logger.info("asset balance is " + assetOwnerAssetBalance); + return assetOwnerAssetBalance; + } + + + /** + * constructor. + */ + /* + public static Optional getDeferredTransactionById(String txId, + WalletGrpc.WalletBlockingStub blockingStubFull) { + ByteString bsTxid = ByteString.copyFrom(ByteArray.fromHexString(txId)); + BytesMessage request = BytesMessage.newBuilder().setValue(bsTxid).build(); + DeferredTransaction transaction = blockingStubFull.getDeferredTransactionById(request); + if (Objects.isNull(transaction)) { + transaction = blockingStubFull.getDeferredTransactionById(request); + } + return Optional.ofNullable(transaction); + } + */ + + + /** * constructor. */ @@ -1020,6 +1589,8 @@ public static boolean transferAsset(byte[] to, byte[] assertName, long amount, b return response.getResult(); } + + /** * constructor. */ @@ -1582,13 +2153,128 @@ public static boolean sellStorage(long quantity, byte[] address, "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); transaction = signTransaction(ecKey, transaction); GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); - return response.getResult(); + return response.getResult(); + } + + /** + * constructor. + */ + public static byte[] deployContract(String contractName, String abiString, String code, + String data, Long feeLimit, long value, + long consumeUserResourcePercent, long originEnergyLimit, String tokenId, long tokenValue, + String libraryAddress, String priKey, byte[] ownerAddress, + WalletGrpc.WalletBlockingStub blockingStubFull) { + Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); + ECKey temKey = null; + try { + BigInteger priK = new BigInteger(priKey, 16); + temKey = ECKey.fromPrivate(priK); + } catch (Exception ex) { + ex.printStackTrace(); + } + final ECKey ecKey = temKey; + + byte[] owner = ownerAddress; + SmartContract.ABI abi = jsonStr2Abi(abiString); + if (abi == null) { + logger.error("abi is null"); + return null; + } + //byte[] codeBytes = Hex.decode(code); + SmartContract.Builder builder = SmartContract.newBuilder(); + builder.setName(contractName); + builder.setOriginAddress(ByteString.copyFrom(owner)); + builder.setAbi(abi); + builder.setConsumeUserResourcePercent(consumeUserResourcePercent); + builder.setOriginEnergyLimit(originEnergyLimit); + + if (value != 0) { + + builder.setCallValue(value); + } + + byte[] byteCode; + if (null != libraryAddress) { + byteCode = replaceLibraryAddress(code, libraryAddress); + } else { + byteCode = Hex.decode(code); + } + builder.setBytecode(ByteString.copyFrom(byteCode)); + + Builder contractBuilder = CreateSmartContract.newBuilder(); + contractBuilder.setOwnerAddress(ByteString.copyFrom(owner)); + contractBuilder.setCallTokenValue(tokenValue); + contractBuilder.setTokenId(Long.parseLong(tokenId)); + CreateSmartContract contractDeployContract = contractBuilder + .setNewContract(builder.build()).build(); + + TransactionExtention transactionExtention = blockingStubFull + .deployContract(contractDeployContract); + if (transactionExtention == null || !transactionExtention.getResult().getResult()) { + System.out.println("RPC create trx failed!"); + if (transactionExtention != null) { + System.out.println("Code = " + transactionExtention.getResult().getCode()); + System.out + .println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); + } + return null; + } + + final TransactionExtention.Builder texBuilder = TransactionExtention.newBuilder(); + Transaction.Builder transBuilder = Transaction.newBuilder(); + Transaction.raw.Builder rawBuilder = transactionExtention.getTransaction().getRawData() + .toBuilder(); + rawBuilder.setFeeLimit(feeLimit); + transBuilder.setRawData(rawBuilder); + for (int i = 0; i < transactionExtention.getTransaction().getSignatureCount(); i++) { + ByteString s = transactionExtention.getTransaction().getSignature(i); + transBuilder.setSignature(i, s); + } + for (int i = 0; i < transactionExtention.getTransaction().getRetCount(); i++) { + Result r = transactionExtention.getTransaction().getRet(i); + transBuilder.setRet(i, r); + } + texBuilder.setTransaction(transBuilder); + texBuilder.setResult(transactionExtention.getResult()); + texBuilder.setTxid(transactionExtention.getTxid()); + transactionExtention = texBuilder.build(); + + byte[] contractAddress = generateContractAddress(transactionExtention.getTransaction(), owner); + System.out.println( + "Your smart contract address will be: " + WalletClient.encode58Check(contractAddress)); + if (transactionExtention == null) { + return null; + } + Return ret = transactionExtention.getResult(); + if (!ret.getResult()) { + System.out.println("Code = " + ret.getCode()); + System.out.println("Message = " + ret.getMessage().toStringUtf8()); + return null; + } + Transaction transaction = transactionExtention.getTransaction(); + if (transaction == null || transaction.getRawData().getContractCount() == 0) { + System.out.println("Transaction is empty"); + return null; + } + transaction = signTransaction(ecKey, transaction); + System.out.println( + "txid = " + ByteArray.toHexString(Sha256Hash.hash(transaction.getRawData().toByteArray()))); + contractAddress = generateContractAddress(transaction, owner); + System.out.println( + "Your smart contract address will be: " + WalletClient.encode58Check(contractAddress)); + + GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); + if (response.getResult() == false) { + return null; + } else { + //logger.info("brodacast succesfully"); + return contractAddress; + } } /** * constructor. */ - public static byte[] deployContract(String contractName, String abiString, String code, String data, Long feeLimit, long value, long consumeUserResourcePercent, String libraryAddress, String priKey, byte[] ownerAddress, @@ -1602,10 +2288,10 @@ public static byte[] deployContract(String contractName, String abiString, Strin * constructor. */ - public static byte[] deployContract(String contractName, String abiString, String code, + public static byte[] deployContractForLibrary(String contractName, String abiString, String code, String data, Long feeLimit, long value, - long consumeUserResourcePercent, long originEnergyLimit, String tokenId, long tokenValue, - String libraryAddress, String priKey, byte[] ownerAddress, + long consumeUserResourcePercent, String libraryAddress, String priKey, byte[] ownerAddress, + String compilerVersion, WalletGrpc.WalletBlockingStub blockingStubFull) { Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); ECKey temKey = null; @@ -1629,7 +2315,7 @@ public static byte[] deployContract(String contractName, String abiString, Strin builder.setOriginAddress(ByteString.copyFrom(owner)); builder.setAbi(abi); builder.setConsumeUserResourcePercent(consumeUserResourcePercent); - builder.setOriginEnergyLimit(originEnergyLimit); + builder.setOriginEnergyLimit(1000L); if (value != 0) { @@ -1638,7 +2324,13 @@ public static byte[] deployContract(String contractName, String abiString, Strin byte[] byteCode; if (null != libraryAddress) { - byteCode = replaceLibraryAddress(code, libraryAddress); + if (compilerVersion.equals("v5") || compilerVersion.equals("V5")) { + byteCode = replaceLibraryAddresscompilerVersion(code, libraryAddress, "v5"); + } else { + //old version + byteCode = replaceLibraryAddresscompilerVersion(code, libraryAddress, null); + } + } else { byteCode = Hex.decode(code); } @@ -1646,8 +2338,8 @@ public static byte[] deployContract(String contractName, String abiString, Strin Builder contractBuilder = CreateSmartContract.newBuilder(); contractBuilder.setOwnerAddress(ByteString.copyFrom(owner)); - contractBuilder.setCallTokenValue(tokenValue); - contractBuilder.setTokenId(Long.parseLong(tokenId)); + contractBuilder.setCallTokenValue(0); + contractBuilder.setTokenId(Long.parseLong("0")); CreateSmartContract contractDeployContract = contractBuilder .setNewContract(builder.build()).build(); @@ -1713,6 +2405,7 @@ public static byte[] deployContract(String contractName, String abiString, Strin //logger.info("brodacast succesfully"); return contractAddress; } + } /** @@ -1812,6 +2505,7 @@ public static String deployContractAndGetTransactionInfoById(String contractName texBuilder.setTxid(transactionExtention.getTxid()); transactionExtention = texBuilder.build(); + if (transactionExtention == null) { return null; } @@ -2061,6 +2755,49 @@ private static byte[] replaceLibraryAddress_1(String code, byte[] libraryAddress return Hex.decode(code); } + private static byte[] replaceLibraryAddresscompilerVersion(String code, String libraryAddressPair, + String compilerVersion) { + + String[] libraryAddressList = libraryAddressPair.split("[,]"); + + for (int i = 0; i < libraryAddressList.length; i++) { + String cur = libraryAddressList[i]; + + int lastPosition = cur.lastIndexOf(":"); + if (-1 == lastPosition) { + throw new RuntimeException("libraryAddress delimit by ':'"); + } + String libraryName = cur.substring(0, lastPosition); + String addr = cur.substring(lastPosition + 1); + String libraryAddressHex; + try { + libraryAddressHex = (new String(Hex.encode(Wallet.decodeFromBase58Check(addr)), + "US-ASCII")).substring(2); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); // now ignore + } + + String beReplaced; + if (compilerVersion == null) { + //old version + String repeated = new String(new char[40 - libraryName.length() - 2]).replace("\0", "_"); + beReplaced = "__" + libraryName + repeated; + } else if (compilerVersion.equalsIgnoreCase("v5")) { + //0.5.4 version + String libraryNameKeccak256 = ByteArray + .toHexString(Hash.sha3(ByteArray.fromString(libraryName))).substring(0, 34); + beReplaced = "__\\$" + libraryNameKeccak256 + "\\$__"; + } else { + throw new RuntimeException("unknown compiler version."); + } + + Matcher m = Pattern.compile(beReplaced).matcher(code); + code = m.replaceAll(libraryAddressHex); + } + + return Hex.decode(code); + } + /** * constructor. */ @@ -2117,6 +2854,187 @@ public static boolean updateSetting(byte[] contractAddress, long consumeUserReso return response.getResult(); } + /** + * constructor. + */ + + public static boolean updateSettingDelay(byte[] contractAddress, + long consumeUserResourcePercent,long delaySeconds, String priKey, byte[] ownerAddress, + WalletGrpc.WalletBlockingStub blockingStubFull) { + Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); + ECKey temKey = null; + try { + BigInteger priK = new BigInteger(priKey, 16); + temKey = ECKey.fromPrivate(priK); + } catch (Exception ex) { + ex.printStackTrace(); + } + final ECKey ecKey = temKey; + + byte[] owner = ownerAddress; + Contract.UpdateSettingContract.Builder builder = Contract.UpdateSettingContract.newBuilder(); + builder.setOwnerAddress(ByteString.copyFrom(owner)); + builder.setContractAddress(ByteString.copyFrom(contractAddress)); + builder.setConsumeUserResourcePercent(consumeUserResourcePercent); + + UpdateSettingContract updateSettingContract = builder.build(); + TransactionExtention transactionExtention = blockingStubFull + .updateSetting(updateSettingContract); + if (transactionExtention == null || !transactionExtention.getResult().getResult()) { + System.out.println("RPC create trx failed!"); + if (transactionExtention != null) { + System.out.println("Code = " + transactionExtention.getResult().getCode()); + System.out + .println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); + } + return false; + } + /* transactionExtention = TransactionUtils.setDelaySecondsToExtension( + transactionExtention, delaySeconds); + if (transactionExtention == null) { + return false; + } + Return ret = transactionExtention.getResult(); + if (!ret.getResult()) { + System.out.println("Code = " + ret.getCode()); + System.out.println("Message = " + ret.getMessage().toStringUtf8()); + return false; + } + Transaction transaction = transactionExtention.getTransaction(); + if (transaction == null || transaction.getRawData().getContractCount() == 0) { + System.out.println("Transaction is empty"); + return false; + } + System.out.println( + "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); + transaction = signTransaction(ecKey, transaction); + GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); + return response.getResult();*/ + return false; + } + + /** + * constructor. + */ + + public static String updateSettingDelayGetTxid(byte[] contractAddress, + long consumeUserResourcePercent,long delaySeconds, + String priKey, byte[] ownerAddress, WalletGrpc + .WalletBlockingStub blockingStubFull) { + Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); + ECKey temKey = null; + try { + BigInteger priK = new BigInteger(priKey, 16); + temKey = ECKey.fromPrivate(priK); + } catch (Exception ex) { + ex.printStackTrace(); + } + final ECKey ecKey = temKey; + + byte[] owner = ownerAddress; + Contract.UpdateSettingContract.Builder builder = Contract.UpdateSettingContract.newBuilder(); + builder.setOwnerAddress(ByteString.copyFrom(owner)); + builder.setContractAddress(ByteString.copyFrom(contractAddress)); + builder.setConsumeUserResourcePercent(consumeUserResourcePercent); + + UpdateSettingContract updateSettingContract = builder.build(); + TransactionExtention transactionExtention = blockingStubFull + .updateSetting(updateSettingContract); + if (transactionExtention == null || !transactionExtention.getResult().getResult()) { + System.out.println("RPC create trx failed!"); + if (transactionExtention != null) { + System.out.println("Code = " + transactionExtention.getResult().getCode()); + System.out + .println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); + } + return null; + } + /* transactionExtention = TransactionUtils.setDelaySecondsToExtension( + transactionExtention, delaySeconds); + if (transactionExtention == null) { + return null; + } + Return ret = transactionExtention.getResult(); + if (!ret.getResult()) { + System.out.println("Code = " + ret.getCode()); + System.out.println("Message = " + ret.getMessage().toStringUtf8()); + return null; + } + Transaction transaction = transactionExtention.getTransaction(); + if (transaction == null || transaction.getRawData().getContractCount() == 0) { + System.out.println("Transaction is empty"); + return null; + } + System.out.println( + "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); + transaction = signTransaction(ecKey, transaction); + GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); + + return ByteArray.toHexString(Sha256Hash.hash(transaction.getRawData().toByteArray()));*/ + return null; + } + + /** + * constructor. + */ + public static String updateEnergyLimitDelayGetTxid(byte[] contractAddress, + long originEnergyLimit,long delaySeconds, String priKey, byte[] ownerAddress, + WalletGrpc.WalletBlockingStub blockingStubFull) { + Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); + ECKey temKey = null; + try { + BigInteger priK = new BigInteger(priKey, 16); + temKey = ECKey.fromPrivate(priK); + } catch (Exception ex) { + ex.printStackTrace(); + } + final ECKey ecKey = temKey; + + byte[] owner = ownerAddress; + Contract.UpdateEnergyLimitContract.Builder builder = Contract.UpdateEnergyLimitContract + .newBuilder(); + builder.setOwnerAddress(ByteString.copyFrom(owner)); + builder.setContractAddress(ByteString.copyFrom(contractAddress)); + builder.setOriginEnergyLimit(originEnergyLimit); + + UpdateEnergyLimitContract updateEnergyLimitContract = builder.build(); + TransactionExtention transactionExtention = blockingStubFull + .updateEnergyLimit(updateEnergyLimitContract); + if (transactionExtention == null || !transactionExtention.getResult().getResult()) { + System.out.println("RPC create trx failed!"); + if (transactionExtention != null) { + System.out.println("Code = " + transactionExtention.getResult().getCode()); + System.out + .println("Message = " + transactionExtention.getResult().getMessage().toStringUtf8()); + } + return null; + } + //transactionExtention = TransactionUtils.setDelaySecondsToExtension( + // transactionExtention, delaySeconds); + if (transactionExtention == null) { + return null; + } + Return ret = transactionExtention.getResult(); + if (!ret.getResult()) { + System.out.println("Code = " + ret.getCode()); + System.out.println("Message = " + ret.getMessage().toStringUtf8()); + return null; + } + Transaction transaction = transactionExtention.getTransaction(); + if (transaction == null || transaction.getRawData().getContractCount() == 0) { + System.out.println("Transaction is empty"); + return null; + } + System.out.println( + "Receive txid = " + ByteArray.toHexString(transactionExtention.getTxid().toByteArray())); + transaction = signTransaction(ecKey, transaction); + GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); + return ByteArray.toHexString(Sha256Hash.hash(transaction.getRawData().toByteArray())); + } + + + + /** * 61 constructor. */ @@ -3197,12 +4115,6 @@ public static boolean updateEnergyLimit(byte[] contractAddress, long originEnerg transaction = signTransaction(ecKey, transaction); GrpcAPI.Return response = broadcastTransaction(transaction, blockingStubFull); return response.getResult(); - /*if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - return true; - }*/ } /** @@ -3347,4 +4259,132 @@ public static GrpcAPI.Return broadcastTransaction(Transaction transaction, return response; } + /** + * constructor. + */ + public static String exec(String command) throws InterruptedException { + String returnString = ""; + Process pro = null; + Runtime runTime = Runtime.getRuntime(); + if (runTime == null) { + logger.error("Create runtime false!"); + } + try { + pro = runTime.exec(command); + BufferedReader input = new BufferedReader(new InputStreamReader(pro.getInputStream())); + PrintWriter output = new PrintWriter(new OutputStreamWriter(pro.getOutputStream())); + String line; + while ((line = input.readLine()) != null) { + returnString = returnString + line + "\n"; + } + input.close(); + output.close(); + pro.destroy(); + } catch (IOException ex) { + logger.error(null, ex); + } + return returnString; + } + + /** + * constructor. + */ + public static HashMap getBycodeAbi(String solFile, String contractName) { + final String compile = Configuration.getByPath("testng.conf") + .getString("defaultParameter.solidityCompile"); + + String dirPath = solFile.substring(solFile.lastIndexOf("/"), solFile.lastIndexOf(".")); + String outputPath = "src/test/resources/soliditycode/output" + dirPath; + + File binFile = new File(outputPath + "/" + contractName + ".bin"); + File abiFile = new File(outputPath + "/" + contractName + ".abi"); + if (binFile.exists()) { + binFile.delete(); + } + if (abiFile.exists()) { + abiFile.delete(); + } + + HashMap retMap = new HashMap<>(); + String absolutePath = System.getProperty("user.dir"); + logger.debug("absolutePath: " + absolutePath); + logger.debug("solFile: " + solFile); + logger.debug("outputPath: " + outputPath); + String cmd = + compile + " --optimize --bin --abi --overwrite " + solFile + " -o " + + absolutePath + "/" + outputPath; + logger.debug("cmd: " + cmd); + + String byteCode = null; + String abI = null; + + // compile solidity file + try { + exec(cmd); + } catch (InterruptedException e) { + e.printStackTrace(); + } + // get byteCode and ABI + try { + byteCode = fileRead(outputPath + "/" + contractName + ".bin", false); + retMap.put("byteCode", byteCode); + logger.debug("byteCode: " + byteCode); + abI = fileRead(outputPath + "/" + contractName + ".abi", false); + retMap.put("abI", abI); + logger.debug("abI: " + abI); + } catch (Exception e) { + e.printStackTrace(); + } + return retMap; + } + + /** + * constructor. + */ + public static String fileRead(String filePath, boolean isLibrary) throws Exception { + File file = new File(filePath); + FileReader reader = new FileReader(file); + BufferedReader breader = new BufferedReader(reader); + StringBuilder sb = new StringBuilder(); + String s = ""; + if (!isLibrary) { + if ((s = breader.readLine()) != null) { + sb.append(s); + } + breader.close(); + } else { + String fistLine = breader.readLine(); + breader.readLine(); + if ((s = breader.readLine()) != null && !s.equals("")) { + s = s.substring(s.indexOf("-> ") + 3); + sb.append(s + ":"); + } else { + s = fistLine.substring(fistLine.indexOf("__") + 2, fistLine.lastIndexOf("__")); + sb.append(s + ":"); + } + breader.close(); + } + return sb.toString(); + } + + /** + * constructor. + */ + public static HashMap getBycodeAbiForLibrary(String solFile, + String contractName) { + HashMap retMap = null; + String dirPath = solFile.substring(solFile.lastIndexOf("/"), solFile.lastIndexOf(".")); + String outputPath = "src/test/resources/soliditycode/output" + dirPath; + try { + retMap = PublicMethed.getBycodeAbi(solFile, contractName); + String library = fileRead(outputPath + "/" + contractName + ".bin", true); + retMap.put("library", library); + logger.debug("library: " + library); + } catch (Exception e) { + e.printStackTrace(); + } + + return retMap; + } + } \ No newline at end of file diff --git a/src/test/java/stest/tron/wallet/common/client/utils/TransactionUtils.java b/src/test/java/stest/tron/wallet/common/client/utils/TransactionUtils.java index 7c7e37c3456..c927682e5b9 100644 --- a/src/test/java/stest/tron/wallet/common/client/utils/TransactionUtils.java +++ b/src/test/java/stest/tron/wallet/common/client/utils/TransactionUtils.java @@ -21,16 +21,22 @@ import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.tron.api.GrpcAPI; import org.tron.common.crypto.ECKey; import org.tron.common.crypto.ECKey.ECDSASignature; import org.tron.common.utils.Sha256Hash; +//import org.tron.protos.Protocol.DeferredStage; import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.Transaction.Contract; + public class TransactionUtils { private static final Logger logger = LoggerFactory.getLogger("Transaction"); private static final int RESERVE_BALANCE = 10; + public static final int NORMALTRANSACTION = 0; + public static final int UNEXECUTEDDEFERREDTRANSACTION = 1; + public static final int EXECUTINGDEFERREDTRANSACTION = 2; /** * constructor. @@ -184,4 +190,32 @@ public static Transaction setTimestamp(Transaction transaction) { builder.setRawData(rowBuilder.build()); return builder.build(); } + + /** + * constructor. + */ + /* public static Transaction setDelaySeconds(Transaction transaction, long delaySeconds) { + DeferredStage deferredStage = transaction.getRawData().toBuilder() + .getDeferredStage().toBuilder().setDelaySeconds(delaySeconds) + .setStage(UNEXECUTEDDEFERREDTRANSACTION).build(); + Transaction.raw rawData = transaction.toBuilder().getRawData() + .toBuilder().setDeferredStage(deferredStage).build(); + return transaction.toBuilder().setRawData(rawData).build(); + }*/ + + /* *//** + * constructor. + *//* + public static GrpcAPI.TransactionExtention setDelaySecondsToExtension(GrpcAPI + .TransactionExtention transactionExtention, long delaySeconds) { + if (delaySeconds == 0) { + return transactionExtention; + } + GrpcAPI.TransactionExtention.Builder builder = transactionExtention.toBuilder(); + + Transaction transaction = setDelaySeconds(transactionExtention.getTransaction(), delaySeconds); + builder.setTransaction(transaction); + + return builder.build(); + }*/ } diff --git a/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage002.java b/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage002.java index 789a69f1766..060ef78118d 100644 --- a/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage002.java +++ b/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage002.java @@ -2,6 +2,7 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; @@ -90,77 +91,14 @@ public void updateSetting() { logger.info("beforeNetLimit:" + beforeNetLimit); logger.info("beforeNetUsed:" + beforeNetUsed); logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String contractName = "tronNative"; - String code = "608060405260008054600160a060020a03199081166201000117909155600180548216620100021" - + "790556002805482166201000317905560038054821662010004179055600480548216620100051790556005" - + "8054821662010006179055600680549091166201000717905534801561007757600080fd5b506104ce80610" - + "0876000396000f3006080604052600436106100da5763ffffffff7c01000000000000000000000000000000" - + "000000000000000000000000006000350416630a90265081146100df5780630dfb51ac146100fc57806345b" - + "d20101461012d5780634efaaa1b1461014257806352ae1b811461016657806353c4263f1461017b5780635f" - + "d8c710146101905780637c369c90146101a55780637f2b7f93146101ba5780638259d5531461020f5780639" - + "06fbec914610227578063961a8be71461023c578063cee14bb414610251578063ec9928bd14610275578063" - + "fb4f32aa14610292575b600080fd5b3480156100eb57600080fd5b506100fa6004356024356102a7565b005" - + "b34801561010857600080fd5b506101116102dc565b60408051600160a060020a0390921682525190819003" - + "60200190f35b34801561013957600080fd5b506101116102eb565b34801561014e57600080fd5b506100fa6" - + "00160a060020a03600435166024356102fa565b34801561017257600080fd5b50610111610320565b348015" - + "61018757600080fd5b5061011161032f565b34801561019c57600080fd5b506100fa61033e565b348015610" - + "1b157600080fd5b5061011161035d565b3480156101c657600080fd5b506040805160206004803580820135" - + "83810280860185019096528085526100fa95369593946024949385019291829185019084908082843750949" - + "75061036c9650505050505050565b34801561021b57600080fd5b506100fa6004356103c6565b3480156102" - + "3357600080fd5b506101116103f7565b34801561024857600080fd5b50610111610406565b34801561025d5" - + "7600080fd5b506100fa600160a060020a0360043516602435610415565b34801561028157600080fd5b5061" - + "00fa600435602435151561044d565b34801561029e57600080fd5b506100fa610483565b600154604080518" - + "48152602081018490528151600160a060020a0390931692818301926000928290030181855af45050505050" - + "565b600654600160a060020a031681565b600354600160a060020a031681565b816080528060a0526000608" - + "060406080620100016000f4151561031c57600080fd5b5050565b600254600160a060020a031681565b6004" - + "54600160a060020a031681565b600354604051600160a060020a03909116906000818181855af4505050565" - + "b600554600160a060020a031681565b6005546040518251600160a060020a03909216918391908190602080" - + "8501910280838360005b838110156103aa578181015183820152602001610392565b5050505090500191505" - + "0600060405180830381855af450505050565b600654604080518381529051600160a060020a039092169160" - + "208083019260009291908290030181855af450505050565b600054600160a060020a031681565b600154600" - + "160a060020a031681565b6000805460408051600160a060020a038681168252602082018690528251931693" - + "81830193909290918290030181855af45050505050565b60045460408051848152831515602082015281516" - + "00160a060020a0390931692818301926000928290030181855af45050505050565b600254604051600160a0" - + "60020a03909116906000818181855af45050505600a165627a7a7230582076efe233a097282a46d3aefb879" - + "b720ed02a4ad3c6cf053cc5936a01e366c7dc0029"; - String abi = "[{\"constant\":false,\"inputs\":[{\"name\":\"frozen_Balance\",\"type\":\"uint256" - + "\"},{\"name\":\"frozen_Duration\",\"type\":\"uint256\"}],\"name\":\"freezeBalance\",\"o" - + "utputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}" - + ",{\"constant\":true,\"inputs\":[],\"name\":\"deleteProposalAddress\",\"outputs\":[{\"na" - + "me\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type" - + "\"" - + ":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"withdrawBalanceAddress\",\"o" - + "utputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\"" - + ":\"" - + "view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"witnessAddr\"" - + ",\"type\":\"address\"},{\"name\":\"voteValue\",\"type\":\"uint256\"}],\"name\":\"voteUs" - + "ingAssembly\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"typ" - + "e\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"unFreezeBalanceAddress\"" - + ",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability" - + "\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"approveP" - + "roposalAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false," - + "\"" - + "stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"n" - + "ame\":\"withdrawBalance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpay" - + "able\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"createProposa" - + "lAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"state" - + "Mutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":" - + "\"data\",\"type\":\"bytes32[]\"}],\"name\":\"createProposal\",\"outputs\":[],\"payable" - + "\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false," - + "\"inputs\":[{\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"deleteProposal\",\"outpu" - + "ts\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"" - + "constant\":true,\"inputs\":[],\"name\":\"voteContractAddress\",\"outputs\":[{\"name\":" - + "\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"" - + "function\"},{\"constant\":true,\"inputs\":[],\"name\":\"freezeBalanceAddress\",\"output" - + "s\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view" - + "\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"witnessAddr\",\"" - + "type\":\"address\"},{\"name\":\"voteValue\",\"type\":\"uint256\"}],\"name\":\"voteForS" - + "ingleWitness\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"t" - + "ype\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"id\",\"type\":\"uint25" - + "6\"},{\"name\":\"isApprove\",\"type\":\"bool\"}],\"name\":\"approveProposal\",\"output" - + "s\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"" - + "constant\":false,\"inputs\":[],\"name\":\"unFreezeBalance\",\"outputs\":[],\"payable\"" - + ":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"; + + String filePath = "./src/test/resources/soliditycode/contractLinkage002.sol"; + String contractName = "divideIHaveArgsReturnStorage"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + //Set the consumeUserResourcePercent is -1,Nothing change. byte[] contractAddress; contractAddress = PublicMethed.deployContract(contractName, abi, code, "", diff --git a/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage003.java b/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage003.java index fed33aa63a1..a58ce5764b7 100644 --- a/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage003.java +++ b/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage003.java @@ -2,6 +2,7 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -90,77 +91,14 @@ public void deployWhenNoEnergy() { logger.info("beforeNetLimit:" + beforeNetLimit); logger.info("beforeNetUsed:" + beforeNetUsed); logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String contractName = "tronNative"; - String code = "608060405260008054600160a060020a03199081166201000117909155600180548216620100021" - + "790556002805482166201000317905560038054821662010004179055600480548216620100051790556005" - + "8054821662010006179055600680549091166201000717905534801561007757600080fd5b506104ce80610" - + "0876000396000f3006080604052600436106100da5763ffffffff7c01000000000000000000000000000000" - + "000000000000000000000000006000350416630a90265081146100df5780630dfb51ac146100fc57806345b" - + "d20101461012d5780634efaaa1b1461014257806352ae1b811461016657806353c4263f1461017b5780635f" - + "d8c710146101905780637c369c90146101a55780637f2b7f93146101ba5780638259d5531461020f5780639" - + "06fbec914610227578063961a8be71461023c578063cee14bb414610251578063ec9928bd14610275578063" - + "fb4f32aa14610292575b600080fd5b3480156100eb57600080fd5b506100fa6004356024356102a7565b005" - + "b34801561010857600080fd5b506101116102dc565b60408051600160a060020a0390921682525190819003" - + "60200190f35b34801561013957600080fd5b506101116102eb565b34801561014e57600080fd5b506100fa6" - + "00160a060020a03600435166024356102fa565b34801561017257600080fd5b50610111610320565b348015" - + "61018757600080fd5b5061011161032f565b34801561019c57600080fd5b506100fa61033e565b348015610" - + "1b157600080fd5b5061011161035d565b3480156101c657600080fd5b506040805160206004803580820135" - + "83810280860185019096528085526100fa95369593946024949385019291829185019084908082843750949" - + "75061036c9650505050505050565b34801561021b57600080fd5b506100fa6004356103c6565b3480156102" - + "3357600080fd5b506101116103f7565b34801561024857600080fd5b50610111610406565b34801561025d5" - + "7600080fd5b506100fa600160a060020a0360043516602435610415565b34801561028157600080fd5b5061" - + "00fa600435602435151561044d565b34801561029e57600080fd5b506100fa610483565b600154604080518" - + "48152602081018490528151600160a060020a0390931692818301926000928290030181855af45050505050" - + "565b600654600160a060020a031681565b600354600160a060020a031681565b816080528060a0526000608" - + "060406080620100016000f4151561031c57600080fd5b5050565b600254600160a060020a031681565b6004" - + "54600160a060020a031681565b600354604051600160a060020a03909116906000818181855af4505050565" - + "b600554600160a060020a031681565b6005546040518251600160a060020a03909216918391908190602080" - + "8501910280838360005b838110156103aa578181015183820152602001610392565b5050505090500191505" - + "0600060405180830381855af450505050565b600654604080518381529051600160a060020a039092169160" - + "208083019260009291908290030181855af450505050565b600054600160a060020a031681565b600154600" - + "160a060020a031681565b6000805460408051600160a060020a038681168252602082018690528251931693" - + "81830193909290918290030181855af45050505050565b60045460408051848152831515602082015281516" - + "00160a060020a0390931692818301926000928290030181855af45050505050565b600254604051600160a0" - + "60020a03909116906000818181855af45050505600a165627a7a7230582076efe233a097282a46d3aefb879" - + "b720ed02a4ad3c6cf053cc5936a01e366c7dc0029"; - String abi = "[{\"constant\":false,\"inputs\":[{\"name\":\"frozen_Balance\",\"type\":\"uint256" - + "\"},{\"name\":\"frozen_Duration\",\"type\":\"uint256\"}],\"name\":\"freezeBalance\",\"o" - + "utputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}" - + ",{\"constant\":true,\"inputs\":[],\"name\":\"deleteProposalAddress\",\"outputs\":[{\"na" - + "me\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type" - + "\"" - + ":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"withdrawBalanceAddress\",\"o" - + "utputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\"" - + ":\"" - + "view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"witnessAddr\"" - + ",\"type\":\"address\"},{\"name\":\"voteValue\",\"type\":\"uint256\"}],\"name\":\"voteUs" - + "ingAssembly\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"typ" - + "e\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"unFreezeBalanceAddress\"" - + ",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability" - + "\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"approveP" - + "roposalAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false," - + "\"" - + "stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"n" - + "ame\":\"withdrawBalance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpay" - + "able\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"createProposa" - + "lAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"state" - + "Mutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":" - + "\"data\",\"type\":\"bytes32[]\"}],\"name\":\"createProposal\",\"outputs\":[],\"payable" - + "\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false," - + "\"inputs\":[{\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"deleteProposal\",\"outpu" - + "ts\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"" - + "constant\":true,\"inputs\":[],\"name\":\"voteContractAddress\",\"outputs\":[{\"name\":" - + "\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"" - + "function\"},{\"constant\":true,\"inputs\":[],\"name\":\"freezeBalanceAddress\",\"output" - + "s\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view" - + "\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"witnessAddr\",\"" - + "type\":\"address\"},{\"name\":\"voteValue\",\"type\":\"uint256\"}],\"name\":\"voteForS" - + "ingleWitness\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"t" - + "ype\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"id\",\"type\":\"uint25" - + "6\"},{\"name\":\"isApprove\",\"type\":\"bool\"}],\"name\":\"approveProposal\",\"output" - + "s\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"" - + "constant\":false,\"inputs\":[],\"name\":\"unFreezeBalance\",\"outputs\":[],\"payable\"" - + ":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"; + + String filePath = "./src/test/resources/soliditycode/contractLinkage003.sol"; + String contractName = "divideIHaveArgsReturnStorage"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + //use FreeNet and balance,EnergyUsed==0. String txid = PublicMethed .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, diff --git a/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage004.java b/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage004.java index bce7804fd11..7856c2229dc 100644 --- a/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage004.java +++ b/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage004.java @@ -2,6 +2,7 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -123,77 +124,13 @@ public void test1GetTransactionInfoById() { logger.info("beforeNetLimit:" + beforeNetLimit); logger.info("beforeNetUsed:" + beforeNetUsed); logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - contractName = "tronNative"; - code = "608060405260008054600160a060020a03199081166201000117909155600180548216620100021" - + "790556002805482166201000317905560038054821662010004179055600480548216620100051790556005" - + "8054821662010006179055600680549091166201000717905534801561007757600080fd5b506104ce80610" - + "0876000396000f3006080604052600436106100da5763ffffffff7c01000000000000000000000000000000" - + "000000000000000000000000006000350416630a90265081146100df5780630dfb51ac146100fc57806345b" - + "d20101461012d5780634efaaa1b1461014257806352ae1b811461016657806353c4263f1461017b5780635f" - + "d8c710146101905780637c369c90146101a55780637f2b7f93146101ba5780638259d5531461020f5780639" - + "06fbec914610227578063961a8be71461023c578063cee14bb414610251578063ec9928bd14610275578063" - + "fb4f32aa14610292575b600080fd5b3480156100eb57600080fd5b506100fa6004356024356102a7565b005" - + "b34801561010857600080fd5b506101116102dc565b60408051600160a060020a0390921682525190819003" - + "60200190f35b34801561013957600080fd5b506101116102eb565b34801561014e57600080fd5b506100fa6" - + "00160a060020a03600435166024356102fa565b34801561017257600080fd5b50610111610320565b348015" - + "61018757600080fd5b5061011161032f565b34801561019c57600080fd5b506100fa61033e565b348015610" - + "1b157600080fd5b5061011161035d565b3480156101c657600080fd5b506040805160206004803580820135" - + "83810280860185019096528085526100fa95369593946024949385019291829185019084908082843750949" - + "75061036c9650505050505050565b34801561021b57600080fd5b506100fa6004356103c6565b3480156102" - + "3357600080fd5b506101116103f7565b34801561024857600080fd5b50610111610406565b34801561025d5" - + "7600080fd5b506100fa600160a060020a0360043516602435610415565b34801561028157600080fd5b5061" - + "00fa600435602435151561044d565b34801561029e57600080fd5b506100fa610483565b600154604080518" - + "48152602081018490528151600160a060020a0390931692818301926000928290030181855af45050505050" - + "565b600654600160a060020a031681565b600354600160a060020a031681565b816080528060a0526000608" - + "060406080620100016000f4151561031c57600080fd5b5050565b600254600160a060020a031681565b6004" - + "54600160a060020a031681565b600354604051600160a060020a03909116906000818181855af4505050565" - + "b600554600160a060020a031681565b6005546040518251600160a060020a03909216918391908190602080" - + "8501910280838360005b838110156103aa578181015183820152602001610392565b5050505090500191505" - + "0600060405180830381855af450505050565b600654604080518381529051600160a060020a039092169160" - + "208083019260009291908290030181855af450505050565b600054600160a060020a031681565b600154600" - + "160a060020a031681565b6000805460408051600160a060020a038681168252602082018690528251931693" - + "81830193909290918290030181855af45050505050565b60045460408051848152831515602082015281516" - + "00160a060020a0390931692818301926000928290030181855af45050505050565b600254604051600160a0" - + "60020a03909116906000818181855af45050505600a165627a7a7230582076efe233a097282a46d3aefb879" - + "b720ed02a4ad3c6cf053cc5936a01e366c7dc0029"; - abi = "[{\"constant\":false,\"inputs\":[{\"name\":\"frozen_Balance\",\"type\":\"uint256" - + "\"},{\"name\":\"frozen_Duration\",\"type\":\"uint256\"}],\"name\":\"freezeBalance\",\"o" - + "utputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}" - + ",{\"constant\":true,\"inputs\":[],\"name\":\"deleteProposalAddress\",\"outputs\":[{\"na" - + "me\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type" - + "\"" - + ":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"withdrawBalanceAddress\",\"o" - + "utputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\"" - + ":\"" - + "view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"witnessAddr\"" - + ",\"type\":\"address\"},{\"name\":\"voteValue\",\"type\":\"uint256\"}],\"name\":\"voteUs" - + "ingAssembly\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"typ" - + "e\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"unFreezeBalanceAddress\"" - + ",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability" - + "\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"approveP" - + "roposalAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false," - + "\"" - + "stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"n" - + "ame\":\"withdrawBalance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpay" - + "able\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"createProposa" - + "lAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"state" - + "Mutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":" - + "\"data\",\"type\":\"bytes32[]\"}],\"name\":\"createProposal\",\"outputs\":[],\"payable" - + "\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false," - + "\"inputs\":[{\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"deleteProposal\",\"outpu" - + "ts\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"" - + "constant\":true,\"inputs\":[],\"name\":\"voteContractAddress\",\"outputs\":[{\"name\":" - + "\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"" - + "function\"},{\"constant\":true,\"inputs\":[],\"name\":\"freezeBalanceAddress\",\"output" - + "s\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view" - + "\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"witnessAddr\",\"" - + "type\":\"address\"},{\"name\":\"voteValue\",\"type\":\"uint256\"}],\"name\":\"voteForS" - + "ingleWitness\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"t" - + "ype\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"id\",\"type\":\"uint25" - + "6\"},{\"name\":\"isApprove\",\"type\":\"bool\"}],\"name\":\"approveProposal\",\"output" - + "s\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"" - + "constant\":false,\"inputs\":[],\"name\":\"unFreezeBalance\",\"outputs\":[],\"payable\"" - + ":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"; + + String filePath = "./src/test/resources/soliditycode/contractLinkage004.sol"; + String contractName = "divideIHaveArgsReturnStorage"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); //use freezeBalanceGetNet,Balance .No freezeBalanceGetenergy String txid = PublicMethed.deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 0L, 50, null, linkage004Key, linkage004Address, blockingStubFull); @@ -261,6 +198,14 @@ public void test2FeeLimitIsTooSmall() { logger.info("beforeNetLimit1:" + beforeNetLimit1); logger.info("beforeNetUsed1:" + beforeNetUsed1); logger.info("beforeFreeNetUsed1:" + beforeFreeNetUsed1); + + String filePath = "./src/test/resources/soliditycode/contractLinkage004.sol"; + String contractName = "divideIHaveArgsReturnStorage"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + String txid = PublicMethed.deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 0L, 50, null, linkage004Key, linkage004Address, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); diff --git a/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage007.java b/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage007.java index 9589b2b2df6..70d7dc54103 100644 --- a/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage007.java +++ b/src/test/java/stest/tron/wallet/contract/linkage/ContractLinkage007.java @@ -2,6 +2,7 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -20,7 +21,6 @@ import org.tron.protos.Protocol.TransactionInfo; import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; import stest.tron.wallet.common.client.utils.PublicMethed; @Slf4j @@ -80,31 +80,7 @@ public void testRangeOfFeeLimit() { //Now the feelimit range is 0-1000000000,including 0 and 1000000000 Assert.assertTrue(PublicMethed.sendcoin(linkage007Address, 2000000000L, fromAddress, testKey002, blockingStubFull)); - contractName = "testRangeOfFeeLimit"; - code = "60806040526000805561026c806100176000396000f3006080604052600436106100565763ffffffff7c01" - + "0000000000000000000000000000000000000000000000000000000060003504166306661abd811461005b5" - + "780631548567714610082578063399ae724146100a8575b600080fd5b34801561006757600080fd5b506100" - + "706100cc565b60408051918252519081900360200190f35b6100a673fffffffffffffffffffffffffffffff" - + "fffffffff600435166024356100d2565b005b6100a673ffffffffffffffffffffffffffffffffffffffff60" - + "0435166024356101af565b60005481565b80600054101561017257600080546001018155604080517f15485" - + "67700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffff" - + "ffffffffffffffffff851660048201526024810184905290513092631548567792604480820193918290030" - + "1818387803b15801561015557600080fd5b505af1158015610169573d6000803e3d6000fd5b505050506100" - + "d2565b8060005414156101ab5760405173ffffffffffffffffffffffffffffffffffffffff8316906000906" - + "0149082818181858883f150505050505b5050565b6000808055604080517f15485677000000000000000000" - + "00000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851" - + "6600482015260248101849052905130926315485677926044808201939182900301818387803b1580156102" - + "2457600080fd5b505af1158015610238573d6000803e3d6000fd5b5050505050505600a165627a7a7230582" - + "0ecdc49ccf0dea5969829debf8845e77be6334f348e9dcaeabf7e98f2d6c7f5270029"; - abi = "[{\"constant\":true,\"inputs\":[],\"name\":\"count\",\"outputs\":[{\"name\":\"\",\"type" - + "\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}," - + "{\"constant\":false,\"inputs\":[{\"name\":\"addr\",\"type\":\"address\"},{\"name\":\"" - + "max\",\"type\":\"uint256\"}],\"name\":\"hack\",\"outputs\":[],\"payable\":true,\"" - + "stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{" - + "\"name\":\"addr\",\"type\":\"address\"},{\"name\":\"max\",\"type\":\"uint256\"}],\"" - + "name\":\"init\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type" - + "\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type" - + "\":\"constructor\"}]"; + AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(linkage007Address, blockingStubFull); Account info; @@ -124,6 +100,14 @@ public void testRangeOfFeeLimit() { logger.info("beforeNetUsed:" + beforeNetUsed); logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); //When the feelimit is large, the deploy will be failed,No used everything. + + String filePath = "./src/test/resources/soliditycode/contractLinkage002.sol"; + String contractName = "divideIHaveArgsReturnStorage"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + String txid; txid = PublicMethed.deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit + 1, 0L, 100, null, linkage007Key, @@ -279,9 +263,10 @@ public void testRangeOfFeeLimit() { logger.info("beforeNetLimit3:" + beforeNetLimit3); logger.info("beforeNetUsed3:" + beforeNetUsed3); logger.info("beforeFreeNetUsed3:" + beforeFreeNetUsed3); - String initParmes = "\"" + Base58.encode58Check(fromAddress) + "\",\"63\""; + //String initParmes = "\"" + Base58.encode58Check(fromAddress) + "\",\"63\""; + String num = "4" + "," + "2"; txid = PublicMethed.triggerContract(contractAddress, - "init(address,uint256)", initParmes, false, + "divideIHaveArgsReturn(int256,int256)", num, false, 1000, maxFeeLimit + 1, linkage007Address, linkage007Key, blockingStubFull); Account infoafter3 = PublicMethed.queryAccount(linkage007Address, blockingStubFull1); PublicMethed.waitProduceNextBlock(blockingStubFull); @@ -325,10 +310,9 @@ public void testRangeOfFeeLimit() { logger.info("beforeNetLimit4:" + beforeNetLimit4); logger.info("beforeNetUsed4:" + beforeNetUsed4); logger.info("beforeFreeNetUsed4:" + beforeFreeNetUsed4); - PublicMethed.triggerContract(contractAddress, - "init(address,uint256)", initParmes, false, - 1000, 0, linkage007Address, linkage007Key, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); + txid = PublicMethed.triggerContract(contractAddress, + "divideIHaveArgsReturn(int256,int256)", num, false, + 1000, maxFeeLimit + 1, linkage007Address, linkage007Key, blockingStubFull); Account infoafter4 = PublicMethed.queryAccount(linkage007Address, blockingStubFull1); AccountResourceMessage resourceInfoafter4 = PublicMethed.getAccountResource(linkage007Address, blockingStubFull1); diff --git a/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario001.java b/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario001.java index 6bcb97e4c2f..37d4a83375c 100644 --- a/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario001.java +++ b/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario001.java @@ -2,6 +2,7 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; @@ -76,7 +77,7 @@ public void deployAddressDemo() { Assert.assertTrue(PublicMethed.sendcoin(contract001Address, 20000000L, toAddress, testKey003, blockingStubFull)); - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(contract001Address, 10000000L, + Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(contract001Address, 15000000L, 3, 1, contract001Key, blockingStubFull)); PublicMethed.waitProduceNextBlock(blockingStubFull1); AccountResourceMessage accountResource = PublicMethed.getAccountResource(contract001Address, @@ -89,18 +90,12 @@ public void deployAddressDemo() { logger.info("before energy usage is " + Long.toString(energyUsage)); logger.info("before balance is " + Long.toString(balanceBefore)); - String contractName = "addressDemo"; - String code = "608060405234801561001057600080fd5b5060bf8061001f6000396000f3006080604052600436" - + "1060485763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041" - + "66313d1aa2e8114604d5780637995b15b146067575b600080fd5b348015605857600080fd5b506065600435" - + "602435608b565b005b348015607257600080fd5b506079608f565b60408051918252519081900360200190f" - + "35b5050565b42905600a165627a7a72305820086db30620ef850edcb987d91625ecf5a1c342dc87dbabb4fe" - + "4b29ec8c1623c10029"; - String abi = "[{\"constant\":false,\"inputs\":[{\"name\":\"start\",\"type\":\"uint256\"},{\"na" - + "me\":\"daysAfter\",\"type\":\"uint256\"}],\"name\":\"f\",\"outputs\":[],\"payable\":fal" - + "se,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inpu" - + "ts\":[],\"name\":\"nowInSeconds\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"" - + "payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"; + String filePath = "./src/test/resources/soliditycode/contractScenario001.sol"; + String contractName = "divideIHaveArgsReturnStorage"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); byte[] contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contract001Key, contract001Address, blockingStubFull); SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); diff --git a/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario003.java b/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario003.java index 2f006e54115..942cbe0e7a3 100644 --- a/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario003.java +++ b/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario003.java @@ -2,6 +2,7 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -88,108 +89,12 @@ public void deployErc223() { logger.info("before energy usage is " + Long.toString(energyUsage)); logger.info("before balance is " + Long.toString(balanceBefore)); - String contractName = "ERC223"; - String code = "60c0604052600560808190527f546f6b656e0000000000000000000000000000000000000000000" - + "0000000000060a090815261003e91600191906100f5565b506040805180820190915260038082527f544b4e" - + "000000000000000000000000000000000000000000000000000000000060209092019182526100839160029" - + "16100f5565b506003805460ff1916601217905534801561009d57600080fd5b50600354735624c12e308b03" - + "a1a6b21d9b86e3942fac1ab92b600090815260205260ff16600a0a622dc6c0027f6a00ac9bafe0f800e80be" - + "817904e734a2f65b971bcec55ae1c1a276cd920b066819055600455610190565b8280546001816001161561" - + "01000203166002900490600052602060002090601f016020900481019282601f1061013657805160ff19168" - + "38001178555610163565b82800160010185558215610163579182015b828111156101635782518255916020" - + "01919060010190610148565b5061016f929150610173565b5090565b61018d91905b8082111561016f57600" - + "08155600101610179565b90565b610a708061019f6000396000f30060806040526004361061007f5763ffff" - + "ffff60e060020a60003504166306fdde03811461008457806318160ddd1461010e578063313ce5671461013" - + "557806333a581d21461016057806370a082311461017557806395d89b4114610196578063a9059cbb146101" - + "ab578063be45fd62146101e3578063f6368f8a1461024c575b600080fd5b34801561009057600080fd5b506" - + "100996102f3565b6040805160208082528351818301528351919283929083019185019080838360005b8381" - + "10156100d35781810151838201526020016100bb565b50505050905090810190601f1680156101005780820" - + "380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561011a" - + "57600080fd5b50610123610388565b60408051918252519081900360200190f35b34801561014157600080f" - + "d5b5061014a61038e565b6040805160ff9092168252519081900360200190f35b34801561016c57600080fd" - + "5b50610123610397565b34801561018157600080fd5b50610123600160a060020a036004351661039d565b3" - + "480156101a257600080fd5b506100996103b8565b3480156101b757600080fd5b506101cf600160a060020a" - + "0360043516602435610416565b604080519115158252519081900360200190f35b3480156101ef57600080f" - + "d5b50604080516020600460443581810135601f81018490048402850184019095528484526101cf94823560" - + "0160a060020a031694602480359536959460649492019190819084018382808284375094975061044c96505" - + "05050505050565b34801561025857600080fd5b50604080516020600460443581810135601f810184900484" - + "02850184019095528484526101cf948235600160a060020a031694602480359536959460649492019190819" - + "084018382808284375050604080516020601f89358b01803591820183900483028401830190945280835297" - + "9a9998810197919650918201945092508291508401838280828437509497506104809650505050505050565" - + "b60018054604080516020601f60026000196101008789161502019095169490940493840181900481028201" - + "81019092528281526060939092909183018282801561037e5780601f1061035357610100808354040283529" - + "16020019161037e565b820191906000526020600020905b8154815290600101906020018083116103615782" - + "9003601f168201915b5050505050905090565b60045490565b60035460ff1690565b60001981565b600160a" - + "060020a031660009081526020819052604090205490565b60028054604080516020601f6000196101006001" - + "871615020190941685900493840181900481028201810190925282815260609390929091830182828015610" - + "37e5780601f106103535761010080835404028352916020019161037e565b60006060610423846106db565b" - + "1561043a576104338484836106e3565b9150610445565b6104338484836108e5565b5092915050565b60006" - + "10457846106db565b1561046e576104678484846106e3565b9050610479565b6104678484846108e5565b93" - + "92505050565b600061048b856106db565b156106c5578361049a3361039d565b10156104a557600080fd5b6" - + "104b76104b13361039d565b85610a17565b336000908152602081905260409020556104d96104d38661039d" - + "565b85610a2c565b600160a060020a038616600081815260208181526040808320949094559251855192939" - + "19286928291908401908083835b602083106105295780518252601f19909201916020918201910161050a56" - + "5b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910" - + "3902060e060020a9004903387876040518563ffffffff1660e060020a0281526004018084600160a060020a" - + "0316600160a060020a03168152602001838152602001828051906020019080838360005b838110156105bb5" - + "781810151838201526020016105a3565b50505050905090810190601f1680156105e8578082038051600183" - + "6020036101000a031916815260200191505b50935050505060006040518083038185885af19350505050151" - + "561060857fe5b84600160a060020a031633600160a060020a03167fe19260aff97b920c7df27010903aeb9c" - + "8d2be5d310a2c67824cf3f15396e4c168686604051808381526020018060200182810382528381815181526" - + "0200191508051906020019080838360005b8381101561068257818101518382015260200161066a565b5050" - + "5050905090810190601f1680156106af5780820380516001836020036101000a031916815260200191505b5" - + "0935050505060405180910390a35060016106d3565b6106d08585856108e5565b90505b949350505050565b" - + "6000903b1190565b600080836106f03361039d565b10156106fb57600080fd5b6107076104b13361039d565" - + "b336000908152602081905260409020556107236104d38661039d565b600160a060020a0386166000818152" - + "602081815260408083209490945592517fc0ee0b8a000000000000000000000000000000000000000000000" - + "0000000000081523360048201818152602483018a90526060604484019081528951606485015289518c9850" - + "959663c0ee0b8a9693958c958c956084909101928601918190849084905b838110156107bf5781810151838" - + "201526020016107a7565b50505050905090810190601f1680156107ec578082038051600183602003610100" - + "0a031916815260200191505b50945050505050600060405180830381600087803b15801561080d57600080f" - + "d5b505af1158015610821573d6000803e3d6000fd5b5050505084600160a060020a031633600160a060020a" - + "03167fe19260aff97b920c7df27010903aeb9c8d2be5d310a2c67824cf3f15396e4c1686866040518083815" - + "260200180602001828103825283818151815260200191508051906020019080838360005b8381101561089f" - + "578181015183820152602001610887565b50505050905090810190601f1680156108cc57808203805160018" - + "36020036101000a031916815260200191505b50935050505060405180910390a3506001949350505050565b" - + "6000826108f13361039d565b10156108fc57600080fd5b61090e6109083361039d565b84610a17565b33600" - + "09081526020819052604090205561093061092a8561039d565b84610a2c565b60008086600160a060020a03" - + "16600160a060020a031681526020019081526020016000208190555083600160a060020a031633600160a06" - + "0020a03167fe19260aff97b920c7df27010903aeb9c8d2be5d310a2c67824cf3f15396e4c16858560405180" - + "83815260200180602001828103825283818151815260200191508051906020019080838360005b838110156" - + "109d25781810151838201526020016109ba565b50505050905090810190601f1680156109ff578082038051" - + "6001836020036101000a031916815260200191505b50935050505060405180910390a350600193925050505" - + "65b600081831015610a2657600080fd5b50900390565b60008160001903831115610a3f57600080fd5b5001" - + "905600a165627a7a723058203115cc5fa7abcc4f08a54831c433f009dcc6c23769428a1373920a7539c8a72" - + "90029"; - String abi = "[{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"_na" - + "me\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"fu" - + "nction\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"nam" - + "e\":\"_totalSupply\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"vie" - + "w\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"out" - + "puts\":[{\"name\":\"_decimals\",\"type\":\"uint8\"}],\"payable\":false,\"stateMutabilit" - + "y\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"MAX_UIN" - + "T256\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMuta" - + "bility\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_ow" - + "ner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"balance\"," - + "\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"functi" - + "on\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"_sy" - + "mbol\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"" - + "function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"" - + "name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"" - + "success\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"t" - + "ype\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"addre" - + "ss\"},{\"name\":\"_value\",\"type\":\"uint256\"},{\"name\":\"_data\",\"type\":\"bytes\"" - + "}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"paya" - + "ble\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":fa" - + "lse,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\"" - + ":\"uint256\"},{\"name\":\"_data\",\"type\":\"bytes\"},{\"name\":\"_custom_fallback\"," - + "\"type\":\"string\"}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"success\",\"type" - + "\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function" - + "\"},{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"co" - + "nstructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_from\",\"t" - + "ype\":\"address\"},{\"indexed\":true,\"name\":\"_to\",\"type\":\"address\"},{\"indexed" - + "\":false,\"name\":\"_value\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"_dat" - + "a\",\"type\":\"bytes\"}],\"name\":\"Transfer\",\"type\":\"event\"}]"; + String filePath = "./src/test/resources/soliditycode/contractScenario003.sol"; + String contractName = "divideIHaveArgsReturnStorage"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); String txid = PublicMethed.deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contract003Key, contract003Address, blockingStubFull); @@ -197,6 +102,8 @@ public void deployErc223() { logger.info(txid); Optional infoById = PublicMethed .getTransactionInfoById(txid, blockingStubFull); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + com.google.protobuf.ByteString contractAddress = infoById.get().getContractAddress(); SmartContract smartContract = PublicMethed .getContract(contractAddress.toByteArray(), blockingStubFull); diff --git a/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario004.java b/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario004.java index c37c760ebbf..9584d73cd5b 100644 --- a/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario004.java +++ b/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario004.java @@ -2,6 +2,8 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; +import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; @@ -16,6 +18,7 @@ import org.tron.common.utils.Utils; import org.tron.core.Wallet; import org.tron.protos.Protocol.SmartContract; +import org.tron.protos.Protocol.TransactionInfo; import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; import stest.tron.wallet.common.client.utils.PublicMethed; @@ -70,13 +73,24 @@ public void deployErc20TronToken() { logger.info("before energy limit is " + Long.toString(energyLimit)); logger.info("before energy usage is " + Long.toString(energyUsage)); - String contractName = "TRONTOKEN"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractScenario004_deployErc20TronToken"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractScenario004_deployErc20TronToken"); - byte[] contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contract004Key, contract004Address, blockingStubFull); + + String filePath = "./src/test/resources/soliditycode/contractScenario004.sol"; + String contractName = "TronToken"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + + byte[] contractAddress; + String txid = PublicMethed + .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, + 0L, 100, null, contract004Key, contract004Address, blockingStubFull); + Optional infoById = PublicMethed + .getTransactionInfoById(txid, blockingStubFull); + logger.info("Txid is " + txid); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + contractAddress = infoById.get().getContractAddress().toByteArray(); + SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); diff --git a/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario005.java b/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario005.java index d4ba96270cf..958dc12fc60 100644 --- a/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario005.java +++ b/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario005.java @@ -2,6 +2,8 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; +import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; @@ -16,6 +18,7 @@ import org.tron.common.utils.Utils; import org.tron.core.Wallet; import org.tron.protos.Protocol.SmartContract; +import org.tron.protos.Protocol.TransactionInfo; import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; import stest.tron.wallet.common.client.utils.PublicMethed; @@ -73,13 +76,23 @@ public void deployIcoContract() { logger.info("before energy limit is " + Long.toString(energyLimit)); logger.info("before energy usage is " + Long.toString(energyUsage)); - String contractName = "ICO"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractScenario005_deployIcoContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractScenario005_deployIcoContract"); - byte[] contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contract005Key, contract005Address, blockingStubFull); + + String filePath = "./src/test/resources/soliditycode/contractScenario005.sol"; + String contractName = "Crowdsale"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + + byte[] contractAddress = null; + String txid = PublicMethed + .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, + 0L, 100, null, contract005Key, contract005Address, blockingStubFull); + Optional infoById = PublicMethed + .getTransactionInfoById(txid, blockingStubFull); + logger.info("Txid is " + txid); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + contractAddress = infoById.get().getContractAddress().toByteArray(); SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); diff --git a/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario006.java b/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario006.java index 0c015c320eb..47ac2572711 100644 --- a/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario006.java +++ b/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario006.java @@ -2,6 +2,8 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; +import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; @@ -16,6 +18,7 @@ import org.tron.common.utils.Utils; import org.tron.core.Wallet; import org.tron.protos.Protocol.SmartContract; +import org.tron.protos.Protocol.TransactionInfo; import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; import stest.tron.wallet.common.client.utils.PublicMethed; @@ -66,12 +69,12 @@ public void deployFomo3D() { contract006Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); PublicMethed.printAddress(contract006Key); - PublicMethed.sendcoin(contract006Address, 200000000L, toAddress, + PublicMethed.sendcoin(contract006Address, 2000000000L, toAddress, testKey003, blockingStubFull); logger.info(Long.toString(PublicMethed.queryAccount(contract006Key, blockingStubFull) .getBalance())); - Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(contract006Address, 10000000L, - 3, 1, contract006Key, blockingStubFull)); + Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(contract006Address, 100000000L, + 0, 1, contract006Key, blockingStubFull)); PublicMethed.waitProduceNextBlock(blockingStubFull); AccountResourceMessage accountResource = PublicMethed.getAccountResource(contract006Address, blockingStubFull); @@ -80,13 +83,23 @@ public void deployFomo3D() { logger.info("before energy limit is " + Long.toString(energyLimit)); logger.info("before energy usage is " + Long.toString(energyUsage)); - String contractName = "Fomo3D"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractScenario006_deployFomo3D"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractScenario006_deployFomo3D"); - byte[] contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contract006Key, contract006Address, blockingStubFull); + + String filePath = "./src/test/resources/soliditycode/contractScenario006.sol"; + String contractName = "FoMo3Dlong"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + + byte[] contractAddress; + String txid = PublicMethed + .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, + 0L, 100, null, contract006Key, contract006Address, blockingStubFull); + Optional infoById = PublicMethed + .getTransactionInfoById(txid, blockingStubFull); + contractAddress = infoById.get().getContractAddress().toByteArray(); + Assert.assertTrue(infoById.get().getResultValue() == 0); + SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); diff --git a/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario007.java b/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario007.java index babf253d28e..c2371f7f0cf 100644 --- a/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario007.java +++ b/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario007.java @@ -2,6 +2,7 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; @@ -76,11 +77,12 @@ public void deployErc721CardMigration() { logger.info("before balance is " + Long.toString(account.getBalance())); logger.info("before energy limit is " + Long.toString(energyLimit)); logger.info("before energy usage is " + Long.toString(energyUsage)); - String contractName = "ERC721"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractScenario007_deployErc721CardMigration"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractScenario007_deployErc721CardMigration"); + String filePath = "./src/test/resources/soliditycode/contractScenario007.sol"; + String contractName = "ERC721Token"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); byte[] contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contract007Key, contract007Address, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); @@ -91,12 +93,13 @@ public void deployErc721CardMigration() { accountResource = PublicMethed.getAccountResource(contract007Address, blockingStubFull); energyLimit = accountResource.getEnergyLimit(); energyUsage = accountResource.getEnergyUsed(); - Assert.assertTrue(energyLimit > 0); - Assert.assertTrue(energyUsage > 0); account = PublicMethed.queryAccount(contract007Key, blockingStubFull); logger.info("after balance is " + Long.toString(account.getBalance())); logger.info("after energy limit is " + Long.toString(energyLimit)); logger.info("after energy usage is " + Long.toString(energyUsage)); + Assert.assertTrue(energyLimit > 0); + Assert.assertTrue(energyUsage > 0); + } /** diff --git a/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario008.java b/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario008.java index 38612a6a5d9..4f306b7daef 100644 --- a/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario008.java +++ b/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario008.java @@ -2,6 +2,7 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; @@ -76,11 +77,13 @@ public void deployErc721CryptoKitties() { logger.info("before energy limit is " + Long.toString(energyLimit)); logger.info("before energy usage is " + Long.toString(energyUsage)); Long shortFeeLimit = 900L; - String contractName = "Cat"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractScenario008_deployErc721CryptoKitties"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractScenario008_deployErc721CryptoKitties"); + + String filePath = "./src/test/resources/soliditycode/contractScenario008.sol"; + String contractName = "KittyCore"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); byte[] contractAddress = PublicMethed.deployContract(contractName, abi, code, "", shortFeeLimit, 0L, 100, null, contract008Key, contract008Address, blockingStubFull); diff --git a/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario009.java b/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario009.java index 929a9739231..cfa4ea28d72 100644 --- a/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario009.java +++ b/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario009.java @@ -2,6 +2,7 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; @@ -18,6 +19,7 @@ import org.tron.protos.Protocol.SmartContract; import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; +import stest.tron.wallet.common.client.utils.Base58; import stest.tron.wallet.common.client.utils.PublicMethed; @Slf4j @@ -33,6 +35,8 @@ public class ContractScenario009 { .getStringList("fullnode.ip.list").get(0); private Long maxFeeLimit = Configuration.getByPath("testng.conf") .getLong("defaultParameter.maxFeeLimit"); + private String compilerVersion = Configuration.getByPath("testng.conf") + .getString("defaultParameter.solidityCompilerVersion"); ECKey ecKey1 = new ECKey(Utils.getRandom()); byte[] contract009Address = ecKey1.getAddress(); @@ -70,14 +74,34 @@ public void deployContainLibraryContract() { logger.info("before energy limit is " + Long.toString(energyLimit)); logger.info("before energy usage is " + Long.toString(energyUsage)); - String contractName = "Library"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractScenario009_deployContainLibraryContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractScenario009_deployContainLibraryContract"); - byte[] libraryAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contract009Key, contract009Address, blockingStubFull); - SmartContract smartContract = PublicMethed.getContract(libraryAddress, blockingStubFull); + String filePath = "./src/test/resources/soliditycode/contractScenario009.sol"; + String contractName = "Set"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + + byte[] libraryContractAddress; + libraryContractAddress = PublicMethed + .deployContract(contractName, abi, code, "", maxFeeLimit, + 0L, 100, null, contract009Key, contract009Address, blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + contractName = "C"; + retMap = PublicMethed.getBycodeAbiForLibrary(filePath, contractName); + code = retMap.get("byteCode").toString(); + abi = retMap.get("abI").toString(); + String library = retMap.get("library").toString(); + + //String libraryAddress = + // "browser/TvmTest_p1_Grammar_002.sol:Set:" + Base58.encode58Check(libraryContractAddress); + String libraryAddress; + libraryAddress = library + + Base58.encode58Check(libraryContractAddress); + + byte[] contractAddress = PublicMethed + .deployContractForLibrary(contractName, abi, code, "", maxFeeLimit, 0L, 100, libraryAddress, + contract009Key, contract009Address, compilerVersion, blockingStubFull); + SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); Assert.assertFalse(smartContract.getAbi().toString().isEmpty()); Assert.assertTrue(smartContract.getName().equalsIgnoreCase(contractName)); diff --git a/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario010.java b/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario010.java index 0e0a5ca7fb2..2ea380bafe1 100644 --- a/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario010.java +++ b/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario010.java @@ -2,6 +2,7 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; @@ -71,14 +72,18 @@ public void deployContainLibraryContract() { blockingStubFull); Long energyLimit = accountResource.getEnergyLimit(); Long energyUsage = accountResource.getEnergyUsed(); + Long netUsage = accountResource.getNetUsed(); logger.info("before energy limit is " + Long.toString(energyLimit)); logger.info("before energy usage is " + Long.toString(energyUsage)); - String contractName = "Tron_ERC721_Token"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractScenario010_deployContainLibraryContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractScenario010_deployContainLibraryContract"); + logger.info("before Net usage is " + Long.toString(netUsage)); + String filePath = "./src/test/resources/soliditycode/contractScenario010.sol"; + String contractName = "TRON_ERC721"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + byte[] libraryAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contract009Key, contract009Address, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); @@ -91,11 +96,13 @@ public void deployContainLibraryContract() { accountResource = PublicMethed.getAccountResource(contract009Address, blockingStubFull); energyLimit = accountResource.getEnergyLimit(); energyUsage = accountResource.getEnergyUsed(); + netUsage = accountResource.getNetUsed(); Assert.assertTrue(energyLimit > 0); Assert.assertTrue(energyUsage > 0); logger.info("after energy limit is " + Long.toString(energyLimit)); logger.info("after energy usage is " + Long.toString(energyUsage)); + logger.info("after Net usage is " + Long.toString(netUsage)); } /** diff --git a/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario012.java b/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario012.java index 82c89fccf1c..4e496853b48 100644 --- a/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario012.java +++ b/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario012.java @@ -2,6 +2,7 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -16,6 +17,7 @@ import org.tron.common.utils.ByteArray; import org.tron.common.utils.Utils; import org.tron.core.Wallet; +import org.tron.protos.Protocol.Account; import org.tron.protos.Protocol.SmartContract; import org.tron.protos.Protocol.TransactionInfo; import stest.tron.wallet.common.client.Configuration; @@ -88,13 +90,21 @@ public void test1DeployTransactionCoin() { logger.info("before energy limit is " + Long.toString(energyLimit)); logger.info("before energy usage is " + Long.toString(energyUsage)); - String contractName = "TransactionCoin"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractScenario012_deployTransactionCoin"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractScenario012_deployTransactionCoin"); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contract012Key, contract012Address, blockingStubFull); + String filePath = "./src/test/resources/soliditycode/contractScenario012.sol"; + String contractName = "PayTest"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + String txid = PublicMethed + .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 0L, 100, + null, contract012Key, contract012Address, blockingStubFull); + infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); + logger.info("infobyid : --- " + infoById); + Assert.assertTrue(infoById.get().getResultValue() == 0); + logger.info("energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + + contractAddress = infoById.get().getContractAddress().toByteArray(); SmartContract smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); Assert.assertTrue(smartContract.getAbi() != null); } @@ -102,6 +112,8 @@ public void test1DeployTransactionCoin() { @Test(enabled = true) public void test2TriggerTransactionCoin() { + Account account = PublicMethed.queryAccount(contractAddress, blockingStubFull); + logger.info("contract Balance : -- " + account.getBalance()); receiveAddressParam = "\"" + Base58.encode58Check(fromAddress) + "\""; //When the contract has no money,transaction coin failed. @@ -111,6 +123,7 @@ public void test2TriggerTransactionCoin() { PublicMethed.waitProduceNextBlock(blockingStubFull); logger.info(txid); infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); + logger.info("infobyid : --- " + infoById); Assert.assertTrue(infoById.get().getResultValue() == 1); logger.info("energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() > 0); @@ -128,7 +141,8 @@ public void test3TriggerTransactionCanNotCreateAccount() { //Send some trx to the contract account. Assert.assertTrue(PublicMethed.sendcoin(contractAddress, 1000000000L, toAddress, testKey003, blockingStubFull)); - + Account account = PublicMethed.queryAccount(contractAddress, blockingStubFull); + logger.info("contract Balance : -- " + account.getBalance()); receiveAddressParam = "\"" + Base58.encode58Check(receiverAddress) + "\""; //In smart contract, you can't create account @@ -138,7 +152,9 @@ public void test3TriggerTransactionCanNotCreateAccount() { PublicMethed.waitProduceNextBlock(blockingStubFull); logger.info(txid); infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); + logger.info("infobyid : --- " + infoById); logger.info("result is " + infoById.get().getResultValue()); + logger.info("energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); Assert.assertTrue(infoById.get().getResultValue() == 1); Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() > 0); Assert.assertTrue(infoById.get().getFee() == infoById.get().getReceipt().getEnergyFee()); @@ -151,6 +167,8 @@ public void test3TriggerTransactionCanNotCreateAccount() { public void test4TriggerTransactionCoin() { receiveAddressParam = "\"" + Base58.encode58Check(receiverAddress) + "\""; + Account account = PublicMethed.queryAccount(contractAddress, blockingStubFull); + logger.info("contract Balance : -- " + account.getBalance()); //This time, trigger the methed sendToAddress2 is OK. Assert.assertTrue(PublicMethed.sendcoin(receiverAddress, 10000000L, toAddress, testKey003, blockingStubFull)); @@ -160,7 +178,9 @@ public void test4TriggerTransactionCoin() { PublicMethed.waitProduceNextBlock(blockingStubFull); logger.info(txid); infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); + logger.info("infobyid : --- " + infoById); logger.info("result is " + infoById.get().getResultValue()); + logger.info("energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); Assert.assertTrue(infoById.get().getResultValue() == 0); Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() > 0); Assert.assertTrue(infoById.get().getFee() == infoById.get().getReceipt().getEnergyFee()); diff --git a/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario013.java b/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario013.java index 45f16f2b29e..4e27f167548 100644 --- a/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario013.java +++ b/src/test/java/stest/tron/wallet/contract/scenario/ContractScenario013.java @@ -2,6 +2,7 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -16,11 +17,9 @@ import org.tron.common.utils.ByteArray; import org.tron.common.utils.Utils; import org.tron.core.Wallet; -import org.tron.protos.Protocol.SmartContract; import org.tron.protos.Protocol.TransactionInfo; import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; -import stest.tron.wallet.common.client.utils.Base58; import stest.tron.wallet.common.client.utils.PublicMethed; @Slf4j @@ -75,15 +74,19 @@ public void deployTronTrxAndSunContract() { logger.info("before energy limit is " + Long.toString(energyLimit)); logger.info("before energy usage is " + Long.toString(energyUsage)); - String contractName = "TronTrxAndSunContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractScenario013_deployTronTrxAndSunContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractScenario013_deployTronTrxAndSunContract"); + + String filePath = "./src/test/resources/soliditycode/contractScenario013.sol"; + String contractName = "timetest"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + txid = PublicMethed.deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contract013Key, contract013Address, blockingStubFull); logger.info(txid); infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); + logger.info("energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); Assert.assertTrue(infoById.get().getResultValue() == 0); Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() > 0); Assert.assertFalse(infoById.get().getContractAddress().isEmpty()); @@ -98,19 +101,30 @@ public void triggerTronTrxAndSunContract() { logger.info("before energy limit is " + Long.toString(energyLimit)); logger.info("before energy usage is " + Long.toString(energyUsage)); - String contractName = "TronTrxAndSunContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractScenario013_triggerTronTrxAndSunContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractScenario013_triggerTronTrxAndSunContract"); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, contract013Key, contract013Address, blockingStubFull); + + String filePath = "./src/test/resources/soliditycode/contractScenario013.sol"; + String contractName = "timetest"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + + String txid = PublicMethed + .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, + 0L, 100, null, contract013Key, contract013Address, blockingStubFull); + infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); + Assert.assertTrue(infoById.get().getResultValue() == 0); + logger.info("energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + + contractAddress = infoById.get().getContractAddress().toByteArray(); + txid = PublicMethed.triggerContract(contractAddress, "time()", "#", false, 0, 100000000L, contract013Address, contract013Key, blockingStubFull); logger.info(txid); infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); logger.info("result is " + infoById.get().getResultValue()); + logger.info("energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); Assert.assertTrue(infoById.get().getResultValue() == 0); Assert.assertTrue(infoById.get().getReceipt().getEnergyUsageTotal() > 0); Assert.assertTrue(infoById.get().getFee() == infoById.get().getReceipt().getEnergyFee()); diff --git a/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue003.java b/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue003.java index 20317a78e12..2f9d819068e 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue003.java +++ b/src/test/java/stest/tron/wallet/dailybuild/assetissue/WalletTestAssetIssue003.java @@ -45,6 +45,8 @@ public class WalletTestAssetIssue003 { private static final String shortname = "a"; private static final String tooLongName = "qazxswedcvfrtgbnhyujmkiolpoiuytre"; private static final String chineseAssetIssuename = "中文都名字"; + private static final String tooLongAbbreviation = "wazxswedcvfrtgbnhyujmkiolpoiuytre"; + private static final String chineseAbbreviation = "中文的简称"; private static final String tooLongDescription = "1qazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqa" + "zxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvq" @@ -163,14 +165,30 @@ public void testExceptionOfAssetIssuew() { Assert.assertFalse(PublicMethed.createAssetIssue(fromAddress, chineseAssetIssuename, totalSupply, 1, 10, start, end, 2, description, url, 10000L, 10000L, 1L, 3652L, asset003Key, blockingStubFull)); + //The abbreviation is null. + Assert.assertFalse(PublicMethed.createAssetIssue(fromAddress, name, "", totalSupply, + 1, 10, start, end, 2, description, url, 10000L, 10000L, + 1L, 3652L, asset003Key, blockingStubFull)); + //The abbreviation is large than 33 char. + Assert.assertFalse(PublicMethed.createAssetIssue(fromAddress, name, tooLongAbbreviation, + totalSupply, 1, 10, start, end, 2, description, url, 10000L, + 10000L, 1L, 3652L, asset003Key, blockingStubFull)); + //The abbreviation is chinese name. + Assert.assertFalse(PublicMethed.createAssetIssue(fromAddress, name, chineseAbbreviation, + totalSupply, 1, 10, start, end, 2, description, url, 10000L, + 10000L, 1L, 3652L, asset003Key, blockingStubFull)); //The URL is null. Assert.assertFalse(PublicMethed.createAssetIssue(fromAddress, name, totalSupply, 1, 10, start, end, 2, description, "", 10000L, 10000L, 1L, 3652L, asset003Key, blockingStubFull)); //The URL is too long. - Assert.assertFalse(PublicMethed.createAssetIssue(fromAddress, name, totalSupply, 1, 10, - start, end, 2, description, tooLongUrl, 10000L, 10000L, - 1L, 3652L, asset003Key, blockingStubFull)); + Assert.assertFalse(PublicMethed.createAssetIssue(fromAddress, name, totalSupply, + 1, 10, start, end, 2, description, tooLongUrl, 10000L, + 10000L, 1L, 3652L, asset003Key, blockingStubFull)); + //The description is null. + Assert.assertFalse(PublicMethed.createAssetIssue(fromAddress, name, totalSupply, + 1, 10, start, end, 2, "", url, 10000L, + 10000L, 1L, 3652L, asset003Key, blockingStubFull)); //The description is too long, create failed. Assert.assertFalse(PublicMethed.createAssetIssue(fromAddress, name, totalSupply, 1, 10, start, end, 2, tooLongDescription, url, 10000L, @@ -217,65 +235,6 @@ public void shutdown() throws InterruptedException { } } - /** - * constructor. - */ - - public Boolean createAssetIssue(byte[] address, String name, Long totalSupply, Integer trxNum, - Integer icoNum, Long startTime, Long endTime, - Integer voteScore, String description, String url, Long fronzenAmount, Long frozenDay, - String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - ECKey ecKey = temKey; - Account search = queryAccount(ecKey, blockingStubFull); - - try { - Contract.AssetIssueContract.Builder builder = Contract.AssetIssueContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(address)); - builder.setName(ByteString.copyFrom(name.getBytes())); - builder.setTotalSupply(totalSupply); - builder.setTrxNum(trxNum); - builder.setNum(icoNum); - builder.setStartTime(startTime); - builder.setEndTime(endTime); - builder.setVoteScore(voteScore); - builder.setDescription(ByteString.copyFrom(description.getBytes())); - builder.setFreeAssetNetLimit(10000); - builder.setPublicFreeAssetNetLimit(10000); - builder.setUrl(ByteString.copyFrom(url.getBytes())); - Contract.AssetIssueContract.FrozenSupply.Builder frozenBuilder = - Contract.AssetIssueContract.FrozenSupply - .newBuilder(); - frozenBuilder.setFrozenAmount(fronzenAmount); - frozenBuilder.setFrozenDays(frozenDay); - builder.addFrozenSupply(0, frozenBuilder); - - Transaction transaction = blockingStubFull.createAssetIssue(builder.build()); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - logger.info("transaction == null"); - return false; - } - transaction = signTransaction(ecKey, transaction); - Return response = blockingStubFull.broadcastTransaction(transaction); - if (response.getResult() == false) { - logger.info(ByteArray.toStr(response.getMessage().toByteArray())); - return false; - } else { - logger.info(name); - return true; - } - } catch (Exception ex) { - ex.printStackTrace(); - return false; - } - } - /** * constructor. */ diff --git a/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction001.java b/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction001.java new file mode 100644 index 00000000000..dd960b90ab8 --- /dev/null +++ b/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction001.java @@ -0,0 +1,428 @@ +package stest.tron.wallet.dailybuild.delaytransaction; + +import com.google.protobuf.ByteString; +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import java.math.BigInteger; +import java.util.Objects; +import java.util.Optional; +import java.util.concurrent.TimeUnit; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.spongycastle.util.encoders.Hex; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeSuite; +import org.testng.annotations.Test; +import org.tron.api.GrpcAPI.BytesMessage; +import org.tron.api.GrpcAPI.NumberMessage; +import org.tron.api.GrpcAPI.Return; +import org.tron.api.WalletGrpc; +import org.tron.common.crypto.ECKey; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.Utils; +import org.tron.core.Wallet; +import org.tron.protos.Contract; +import org.tron.protos.Protocol.Account; +import org.tron.protos.Protocol.Block; +//import org.tron.protos.Protocol.DeferredTransaction; +import org.tron.protos.Protocol.Transaction; +import org.tron.protos.Protocol.TransactionInfo; +import stest.tron.wallet.common.client.Configuration; +import stest.tron.wallet.common.client.Parameter.CommonConstant; +import stest.tron.wallet.common.client.utils.Base58; +import stest.tron.wallet.common.client.utils.PublicMethed; +import stest.tron.wallet.common.client.utils.Sha256Hash; +import stest.tron.wallet.common.client.utils.TransactionUtils; + +@Slf4j +public class DelayTransaction001 { + + private final String testKey002 = Configuration.getByPath("testng.conf") + .getString("foundationAccount.key1"); + private final String testKey003 = Configuration.getByPath("testng.conf") + .getString("foundationAccount.key2"); + private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); + private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); + + private ManagedChannel channelFull = null; + private WalletGrpc.WalletBlockingStub blockingStubFull = null; + + private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") + .get(0); + private Long delayTransactionFee = Configuration.getByPath("testng.conf") + .getLong("defaultParameter.delayTransactionFee"); + + + public static final long MAX_DEFERRED_TRANSACTION_DELAY_SECONDS = 45 * 24 * 3_600L; //45 days + Optional infoById = null; + //Optional deferredTransactionById = null; + Optional getTransactionById = null; + + + ECKey ecKey = new ECKey(Utils.getRandom()); + byte[] delayAccount1Address = ecKey.getAddress(); + String delayAccount1Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); + + ECKey ecKey2 = new ECKey(Utils.getRandom()); + byte[] delayAccount2Address = ecKey2.getAddress(); + String delayAccount2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); + + ECKey ecKey3 = new ECKey(Utils.getRandom()); + byte[] receiverAccountAddress = ecKey3.getAddress(); + String receiverAccountKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); + + ECKey ecKey4 = new ECKey(Utils.getRandom()); + byte[] delayAccount3Address = ecKey4.getAddress(); + String delayAccount3Key = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); + + ECKey ecKey5 = new ECKey(Utils.getRandom()); + byte[] receiverAccount4Address = ecKey5.getAddress(); + String receiverAccount4Key = ByteArray.toHexString(ecKey5.getPrivKeyBytes()); + + @BeforeSuite + public void beforeSuite() { + Wallet wallet = new Wallet(); + Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); + } + + /** + * constructor. + */ + + @BeforeClass(enabled = false) + public void beforeClass() { + channelFull = ManagedChannelBuilder.forTarget(fullnode) + .usePlaintext(true) + .build(); + blockingStubFull = WalletGrpc.newBlockingStub(channelFull); + } + + @Test(enabled = false, description = "Delayed send coin to test delayed second") + public void test1DelayedSecond() { + //get account + ecKey = new ECKey(Utils.getRandom()); + delayAccount1Address = ecKey.getAddress(); + delayAccount1Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); + PublicMethed.printAddress(delayAccount1Key); + Assert.assertTrue(PublicMethed.sendcoin(delayAccount1Address, 100000000L,fromAddress, + testKey002, blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + Assert.assertTrue(PublicMethed.sendcoinDelayed(fromAddress, 100000000L, 23L, + delayAccount1Address, delayAccount1Key, blockingStubFull)); + Assert.assertTrue(PublicMethed.sendcoinDelayed(fromAddress, 1L, 0L,delayAccount1Address, + delayAccount1Key, blockingStubFull)); + Assert.assertFalse(PublicMethed.sendcoinDelayed(fromAddress, 1L, -1L,delayAccount1Address, + delayAccount1Key, blockingStubFull)); + Assert.assertFalse(PublicMethed.sendcoinDelayed(fromAddress, 1L, + MAX_DEFERRED_TRANSACTION_DELAY_SECONDS + 1L,delayAccount1Address, delayAccount1Key, + blockingStubFull)); + Assert.assertTrue(PublicMethed.sendcoinDelayed(fromAddress, 1L, + MAX_DEFERRED_TRANSACTION_DELAY_SECONDS,delayAccount1Address, delayAccount1Key, + blockingStubFull)); + } + + /* + @Test(enabled = false, description = "Get deferred transaction by id") + public void test2getDeferredTransactionByid() { + //get account + ECKey ecKey2 = new ECKey(Utils.getRandom()); + byte[] delayAccount2Address = ecKey2.getAddress(); + String delayAccount2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); + + ecKey3 = new ECKey(Utils.getRandom()); + receiverAccountAddress = ecKey3.getAddress(); + receiverAccountKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); + PublicMethed.printAddress(delayAccount2Key); + PublicMethed.printAddress(receiverAccountKey); + + //Pre sendcoin to the test account + Assert.assertTrue(PublicMethed.sendcoin(delayAccount2Address, 100000000L,fromAddress, + testKey002, blockingStubFull)); + Assert.assertTrue(PublicMethed.sendcoin(receiverAccountAddress, 10L,fromAddress, + testKey002, blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + //Do delay send coin transaction. + Long delaySecond = 10L; + Long sendCoinAmout = 100L; + + //Query balance before send coin. + Long deplayAccountBeforeBalance = PublicMethed.queryAccount( + delayAccount2Address, blockingStubFull).getBalance(); + Long recevierAccountBeforeBalance = PublicMethed.queryAccount( + receiverAccountAddress, blockingStubFull).getBalance(); + logger.info("deplayAccountBeforeBalance " + deplayAccountBeforeBalance); + logger.info("recevierAccountBeforeBalance " + recevierAccountBeforeBalance); + String txid = PublicMethed.sendcoinDelayedGetTxid(receiverAccountAddress, + sendCoinAmout, delaySecond,delayAccount2Address, + delayAccount2Key, blockingStubFull); + + PublicMethed.waitProduceNextBlock(blockingStubFull); + + //Query balance when pre-sendcoin stage. + Long deplayAccountInDelayBalance = PublicMethed.queryAccount(delayAccount2Address, + blockingStubFull).getBalance(); + Long recevierAccountInDelayalance = PublicMethed.queryAccount(receiverAccountAddress, + blockingStubFull).getBalance(); + logger.info("deplayAccountInDelayBalance " + deplayAccountInDelayBalance); + logger.info("recevierAccountInDelayalance " + recevierAccountInDelayalance); + Assert.assertTrue(recevierAccountBeforeBalance == recevierAccountInDelayalance); + //Assert.assertTrue(); + + + deferredTransactionById = PublicMethed.getDeferredTransactionById(txid,blockingStubFull); + DeferredTransaction transaction = deferredTransactionById.get(); + String finalTxid = ByteArray.toHexString(Sha256Hash.hash(transaction.getTransaction() + .getRawData().toByteArray())); + PublicMethed.getDeferredTransactionById(finalTxid,blockingStubFull); + logger.info(finalTxid); + //logger.info("receiver address is " + Base58.encode58Check(transaction.getReceiverAddress() + .toByteArray())); + Assert.assertTrue(Base58.encode58Check(transaction.getReceiverAddress().toByteArray()) + .equalsIgnoreCase(PublicMethed.getAddressString(receiverAccountKey))); + //logger.info("sender address is " + Base58.encode58Check(transaction.getSenderAddress() + .toByteArray())); + Assert.assertTrue(Base58.encode58Check(transaction.getSenderAddress().toByteArray()) + .equalsIgnoreCase(PublicMethed.getAddressString(delayAccount2Key))); + // logger.info("delaySeconds is " + transaction.getDelaySeconds()); + Assert.assertTrue(delaySecond == transaction.getDelaySeconds()); + //logger.info("DelayUntil " + transaction.getDelayUntil()); + Assert.assertTrue(transaction.getDelayUntil() > System.currentTimeMillis()); + //logger.info("Expiration " + transaction.getExpiration()); + Assert.assertTrue(transaction.getExpiration() > System.currentTimeMillis()); + //logger.info("PublishTime " + transaction.getPublishTime()); + Assert.assertTrue(transaction.getPublishTime() < System.currentTimeMillis()); + //Assert.assertTrue(transaction.getDelayUntil() + 60000 == transaction.getExpiration()); + getTransactionById = PublicMethed.getTransactionById(txid, blockingStubFull); + logger.info("transaction stage in txid is " + getTransactionById.get().getRawData() + .getDeferredStage().getStage()); + + Assert.assertTrue(getTransactionById.get().getRawData().getDeferredStage().getStage() == 1); + getTransactionById = PublicMethed.getTransactionById(finalTxid, blockingStubFull); + logger.info("transaction stage in final id is " + getTransactionById.get().getRawData() + .getDeferredStage().getStage()); + Assert.assertTrue(getTransactionById.get().getRawData().getDeferredStage().getStage() == 0); + + PublicMethed.waitProduceNextBlock(blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + PublicMethed.getDeferredTransactionById(finalTxid,blockingStubFull); + deferredTransactionById = PublicMethed.getDeferredTransactionById(txid,blockingStubFull); + finalTxid = ByteArray.toHexString(Sha256Hash.hash(transaction.getTransaction().getRawData() + .toByteArray())); + transaction = deferredTransactionById.get(); + logger.info(finalTxid); + //logger.info("receiver address is " + Base58.encode58Check(transaction + .getReceiverAddress().toByteArray())); + //logger.info("receiver address is " + Base58.encode58Check(transaction + .getSenderAddress().toByteArray())); + //logger.info("delaySeconds is " + transaction.getDelaySeconds()); + //logger.info("DelayUntil " + transaction.getDelayUntil()); + //logger.info("Expiration " + transaction.getExpiration()); + //logger.info("PublishTime " + transaction.getPublishTime()); + getTransactionById = PublicMethed.getTransactionById(txid, blockingStubFull); + logger.info("transaction stage in txid is " + getTransactionById.get().getRawData() + .getDeferredStage().getStage()); + getTransactionById = PublicMethed.getTransactionById(finalTxid, blockingStubFull); + logger.info("transaction stage in final id is " + getTransactionById.get() + .getRawData().getDeferredStage().getStage()); + + + + //Query balance after delay send coin. + Long deplayAccountAfterBalance = PublicMethed.queryAccount(delayAccount2Address, + blockingStubFull).getBalance(); + Long recevierAccountAfterDelayalance = PublicMethed.queryAccount(receiverAccountAddress, + blockingStubFull).getBalance(); + logger.info("deplayAccountAfterBalance " + deplayAccountAfterBalance); + logger.info("recevierAccountAfterDelayalance " + recevierAccountAfterDelayalance); + + Assert.assertTrue(deplayAccountBeforeBalance - deplayAccountAfterBalance == sendCoinAmout + + 100000L); + Assert.assertTrue(recevierAccountAfterDelayalance - recevierAccountBeforeBalance == + sendCoinAmout); + + + + }*/ + + @Test(enabled = false, description = "Delay send coin") + public void test3DelaySendCoin() { + ecKey4 = new ECKey(Utils.getRandom()); + delayAccount3Address = ecKey4.getAddress(); + delayAccount3Key = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); + PublicMethed.printAddress(delayAccount3Key); + + ecKey5 = new ECKey(Utils.getRandom()); + receiverAccount4Address = ecKey5.getAddress(); + receiverAccount4Key = ByteArray.toHexString(ecKey5.getPrivKeyBytes()); + PublicMethed.printAddress(receiverAccount4Key); + + Long sendCoinAmount = 100000000L; + //Pre sendcoin to the test account + Assert.assertTrue(PublicMethed.sendcoin(delayAccount3Address, sendCoinAmount,fromAddress, + testKey002, blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + logger.info("----------------No balance to send coin--------------------"); + //Do delay send coin transaction. + Long delaySecond = 4L; + + //Test no balance to send coin. + //Query balance before send coin. + Long deplayAccountBeforeBalance = PublicMethed.queryAccount(delayAccount3Address, + blockingStubFull).getBalance(); + Long recevierAccountBeforeBalance = PublicMethed.queryAccount(receiverAccount4Address, + blockingStubFull).getBalance(); + logger.info("deplayAccountBeforeBalance " + deplayAccountBeforeBalance); + logger.info("recevierAccountBeforeBalance " + recevierAccountBeforeBalance); + Assert.assertFalse(PublicMethed.sendcoinDelayed(receiverAccount4Address, sendCoinAmount, + delaySecond,delayAccount3Address, delayAccount3Key, blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + //Query balance after delay send coin. + Long deplayAccountAfterBalance = PublicMethed.queryAccount(delayAccount3Address, + blockingStubFull).getBalance(); + Long recevierAccountAfterDelayalance = PublicMethed.queryAccount(receiverAccount4Address, + blockingStubFull).getBalance(); + logger.info("deplayAccountAfterBalance " + deplayAccountAfterBalance); + logger.info("recevierAccountAfterDelayalance " + recevierAccountAfterDelayalance); + + Assert.assertTrue(recevierAccountAfterDelayalance == 0); + logger.info("deplayAccountBeforeBalance: " + deplayAccountBeforeBalance); + logger.info("deplayAccountAfterBalance: " + deplayAccountAfterBalance); + + Assert.assertEquals(deplayAccountBeforeBalance,deplayAccountAfterBalance); + + + logger.info("----------------No balance to create account send coin--------------------"); + //Test delay send coin to create account. + deplayAccountBeforeBalance = PublicMethed.queryAccount(delayAccount3Address, + blockingStubFull).getBalance(); + recevierAccountBeforeBalance = PublicMethed.queryAccount(receiverAccount4Address, + blockingStubFull).getBalance(); + logger.info("deplayAccountBeforeBalance " + deplayAccountBeforeBalance); + logger.info("recevierAccountBeforeBalance " + recevierAccountBeforeBalance); + + Long createAccountFee = 100000L; + Assert.assertTrue(PublicMethed.sendcoinDelayed(receiverAccount4Address, + deplayAccountBeforeBalance - createAccountFee, delaySecond,delayAccount3Address, + delayAccount3Key, blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + //Query balance after delay send coin. + deplayAccountAfterBalance = PublicMethed.queryAccount(delayAccount3Address, + blockingStubFull).getBalance(); + recevierAccountAfterDelayalance = PublicMethed.queryAccount(receiverAccount4Address, + blockingStubFull).getBalance(); + logger.info("deplayAccountAfterBalance " + deplayAccountAfterBalance); + logger.info("recevierAccountAfterDelayalance " + recevierAccountAfterDelayalance); + + Assert.assertTrue(recevierAccountAfterDelayalance == 0); + Assert.assertTrue(deplayAccountBeforeBalance - deplayAccountAfterBalance == 100000); + + + logger.info("---------------Balance enough to create account send coin--------------------"); + //Test delay send coin to create account. + createAccountFee = 100000L; + deplayAccountBeforeBalance = PublicMethed.queryAccount(delayAccount3Address, + blockingStubFull).getBalance(); + recevierAccountBeforeBalance = PublicMethed.queryAccount(receiverAccount4Address, + blockingStubFull).getBalance(); + logger.info("deplayAccountBeforeBalance " + deplayAccountBeforeBalance); + logger.info("recevierAccountBeforeBalance " + recevierAccountBeforeBalance); + Assert.assertTrue(PublicMethed.sendcoinDelayed(receiverAccount4Address, + deplayAccountBeforeBalance - createAccountFee - delayTransactionFee, + delaySecond,delayAccount3Address, delayAccount3Key, blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + //Query balance after delay send coin. + deplayAccountAfterBalance = PublicMethed.queryAccount(delayAccount3Address, + blockingStubFull).getBalance(); + recevierAccountAfterDelayalance = PublicMethed.queryAccount(receiverAccount4Address, + blockingStubFull).getBalance(); + logger.info("deplayAccountAfterBalance " + deplayAccountAfterBalance); + logger.info("recevierAccountAfterDelayalance " + recevierAccountAfterDelayalance); + Long receiverBalanceShouldBe = deplayAccountBeforeBalance - createAccountFee + - delayTransactionFee; + + Assert.assertEquals(recevierAccountAfterDelayalance, receiverBalanceShouldBe); + Assert.assertTrue(deplayAccountAfterBalance == 0); + + + } + + @Test(enabled = false, description = "Not enough money to send coin.") + public void test4DelaySendCoin() { + ecKey4 = new ECKey(Utils.getRandom()); + delayAccount3Address = ecKey4.getAddress(); + delayAccount3Key = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); + PublicMethed.printAddress(delayAccount3Key); + + ecKey5 = new ECKey(Utils.getRandom()); + receiverAccount4Address = ecKey5.getAddress(); + receiverAccount4Key = ByteArray.toHexString(ecKey5.getPrivKeyBytes()); + PublicMethed.printAddress(receiverAccount4Key); + + Long sendCoinAmount = 100000000L; + //Pre sendcoin to the test account + Assert.assertTrue(PublicMethed.sendcoin(delayAccount3Address, sendCoinAmount, fromAddress, + testKey002, blockingStubFull)); + Assert.assertTrue(PublicMethed.sendcoin(receiverAccount4Address, sendCoinAmount, fromAddress, + testKey002, blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + //Do delay send coin transaction. + Long createAccountFee = 100000L; + + logger.info("----------------Send all balance to exist account--------------------"); + //Test no balance to send coin. + //Query balance before send coin. + Long deplayAccountBeforeBalance = PublicMethed.queryAccount(delayAccount3Address, + blockingStubFull).getBalance(); + Long recevierAccountBeforeBalance = PublicMethed.queryAccount(receiverAccount4Address, + blockingStubFull).getBalance(); + logger.info("deplayAccountBeforeBalance " + deplayAccountBeforeBalance); + logger.info("recevierAccountBeforeBalance " + recevierAccountBeforeBalance); + + Long delaySecond = 4L; + Assert.assertTrue(PublicMethed.sendcoinDelayed(receiverAccount4Address, sendCoinAmount, + delaySecond,delayAccount3Address, delayAccount3Key, blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + //Query balance after delay send coin. + Long deplayAccountAfterBalance = PublicMethed.queryAccount(delayAccount3Address, + blockingStubFull).getBalance(); + Long recevierAccountAfterDelayalance = PublicMethed.queryAccount(receiverAccount4Address, + blockingStubFull).getBalance(); + logger.info("deplayAccountAfterBalance " + deplayAccountAfterBalance); + logger.info("recevierAccountAfterDelayalance " + recevierAccountAfterDelayalance); + + Assert.assertTrue(recevierAccountAfterDelayalance == 0); + logger.info("deplayAccountBeforeBalance: " + deplayAccountBeforeBalance); + logger.info("deplayAccountAfterBalance: " + deplayAccountAfterBalance); + + Assert.assertEquals(deplayAccountBeforeBalance,deplayAccountAfterBalance); + + + + } + + + + + /** + * constructor. + */ + @AfterClass(enabled = false) + public void shutdown() throws InterruptedException { + if (channelFull != null) { + channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); + } + } +} + + diff --git a/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction002.java b/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction002.java new file mode 100644 index 00000000000..00195a0c031 --- /dev/null +++ b/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction002.java @@ -0,0 +1,255 @@ +package stest.tron.wallet.dailybuild.delaytransaction; + +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import java.util.Optional; +import java.util.concurrent.TimeUnit; +import lombok.extern.slf4j.Slf4j; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeSuite; +import org.testng.annotations.Test; +import org.tron.api.WalletGrpc; +import org.tron.common.crypto.ECKey; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.Utils; +import org.tron.core.Wallet; +//import org.tron.protos.Protocol.DeferredTransaction; +import org.tron.protos.Protocol.Transaction; +import org.tron.protos.Protocol.TransactionInfo; +import stest.tron.wallet.common.client.Configuration; +import stest.tron.wallet.common.client.Parameter.CommonConstant; +import stest.tron.wallet.common.client.utils.Base58; +import stest.tron.wallet.common.client.utils.PublicMethed; +import stest.tron.wallet.common.client.utils.Sha256Hash; + +@Slf4j +public class DelayTransaction002 { + + private final String testKey002 = Configuration.getByPath("testng.conf") + .getString("foundationAccount.key1"); + private final String testKey003 = Configuration.getByPath("testng.conf") + .getString("foundationAccount.key2"); + private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); + private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); + + private ManagedChannel channelFull = null; + private WalletGrpc.WalletBlockingStub blockingStubFull = null; + + private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") + .get(1); + private Long delayTransactionFee = Configuration.getByPath("testng.conf") + .getLong("defaultParameter.delayTransactionFee"); + private Long cancleDelayTransactionFee = Configuration.getByPath("testng.conf") + .getLong("defaultParameter.cancleDelayTransactionFee"); + + + + Optional infoById = null; + //Optional deferredTransactionById = null; + Optional getTransactionById = null; + + + ECKey ecKey = new ECKey(Utils.getRandom()); + byte[] delayAccount1Address = ecKey.getAddress(); + String delayAccount1Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); + + ECKey ecKey2 = new ECKey(Utils.getRandom()); + byte[] delayAccount2Address = ecKey2.getAddress(); + String delayAccount2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); + + ECKey ecKey3 = new ECKey(Utils.getRandom()); + byte[] receiverAccountAddress = ecKey3.getAddress(); + String receiverAccountKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); + + ECKey ecKey4 = new ECKey(Utils.getRandom()); + byte[] delayAccount3Address = ecKey4.getAddress(); + String delayAccount3Key = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); + + ECKey ecKey5 = new ECKey(Utils.getRandom()); + byte[] receiverAccount4Address = ecKey5.getAddress(); + String receiverAccount4Key = ByteArray.toHexString(ecKey5.getPrivKeyBytes()); + + @BeforeSuite + public void beforeSuite() { + Wallet wallet = new Wallet(); + Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); + } + + /** + * constructor. + */ + + @BeforeClass(enabled = false) + public void beforeClass() { + channelFull = ManagedChannelBuilder.forTarget(fullnode) + .usePlaintext(true) + .build(); + blockingStubFull = WalletGrpc.newBlockingStub(channelFull); + } + + @Test(enabled = false, description = "Cancel deferred transaction") + public void test1CancleDeferredTransaction() { + //get account + ecKey = new ECKey(Utils.getRandom()); + delayAccount1Address = ecKey.getAddress(); + delayAccount1Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); + PublicMethed.printAddress(delayAccount1Key); + ecKey3 = new ECKey(Utils.getRandom()); + receiverAccountAddress = ecKey3.getAddress(); + receiverAccountKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); + PublicMethed.printAddress(receiverAccountKey); + + Assert.assertTrue(PublicMethed.sendcoin(delayAccount1Address, 100000000L,fromAddress, + testKey002, blockingStubFull)); + Assert.assertTrue(PublicMethed.sendcoin(receiverAccountAddress, 100L,fromAddress, + testKey002, blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + //Do delay send coin transaction. + Long delaySecond = 10L; + Long sendCoinAmount = 1L; + + //Query balance before send coin. + Long deplayAccountBeforeBalance = PublicMethed.queryAccount(delayAccount1Address, + blockingStubFull).getBalance(); + Long recevierAccountBeforeBalance = PublicMethed.queryAccount(receiverAccountAddress, + blockingStubFull).getBalance(); + logger.info("deplayAccountBeforeBalance " + deplayAccountBeforeBalance); + logger.info("recevierAccountBeforeBalance " + recevierAccountBeforeBalance); + String txid = PublicMethed.sendcoinDelayedGetTxid(receiverAccountAddress, sendCoinAmount, + delaySecond,delayAccount1Address, + delayAccount1Key, blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + //deferredTransactionById = PublicMethed.getDeferredTransactionById(txid,blockingStubFull); + //DeferredTransaction transaction = deferredTransactionById.get(); + //String finalTxid = ByteArray.toHexString(Sha256Hash.hash(transaction.getTransaction() + // .getRawData().toByteArray())); + + //Assert.assertFalse(PublicMethed.cancelDeferredTransactionById(finalTxid,receiverAccountAddress + // ,receiverAccountKey,blockingStubFull)); + Assert.assertFalse(PublicMethed.cancelDeferredTransactionById(txid,receiverAccountAddress, + receiverAccountKey,blockingStubFull)); + Assert.assertTrue(PublicMethed.cancelDeferredTransactionById(txid,delayAccount1Address, + delayAccount1Key,blockingStubFull)); + Assert.assertFalse(PublicMethed.cancelDeferredTransactionById(txid,delayAccount1Address, + delayAccount1Key,blockingStubFull)); + PublicMethed.cancelDeferredTransactionById(txid,delayAccount1Address,delayAccount1Key, + blockingStubFull); + PublicMethed.cancelDeferredTransactionById(txid,delayAccount1Address,delayAccount1Key, + blockingStubFull); + PublicMethed.cancelDeferredTransactionById(txid,delayAccount1Address,delayAccount1Key, + blockingStubFull); + PublicMethed.cancelDeferredTransactionById(txid,delayAccount1Address,delayAccount1Key, + blockingStubFull); + PublicMethed.cancelDeferredTransactionById(txid,delayAccount1Address,delayAccount1Key, + blockingStubFull); + PublicMethed.cancelDeferredTransactionById(txid,delayAccount1Address,delayAccount1Key, + blockingStubFull); + PublicMethed.cancelDeferredTransactionById(txid,delayAccount1Address,delayAccount1Key, + blockingStubFull); + PublicMethed.cancelDeferredTransactionById(txid,delayAccount1Address,delayAccount1Key, + blockingStubFull); + PublicMethed.cancelDeferredTransactionById(txid,delayAccount1Address,delayAccount1Key, + blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + Long deplayAccountAfterBalance = PublicMethed.queryAccount(delayAccount1Address, + blockingStubFull).getBalance(); + Long recevierAccountAfterDelayalance = PublicMethed.queryAccount(receiverAccountAddress, + blockingStubFull).getBalance(); + logger.info("deplayAccountAfterBalance " + deplayAccountAfterBalance); + logger.info("recevierAccountAfterDelayalance " + recevierAccountAfterDelayalance); + //Assert.assertFalse(PublicMethed.cancelDeferredTransactionById(txid,delayAccount1Address, + // delayAccount1Key,blockingStubFull)); + //PublicMethed.cancelDeferredTransactionById(txid,delayAccount1Address,delayAccount1Key, + // blockingStubFull); + //PublicMethed.cancelDeferredTransactionById(txid,delayAccount1Address,delayAccount1Key, + // blockingStubFull); + //PublicMethed.cancelDeferredTransactionById(txid,delayAccount1Address,delayAccount1Key, + // blockingStubFull); + //PublicMethed.cancelDeferredTransactionById(txid,delayAccount1Address,delayAccount1Key, + // blockingStubFull); + //PublicMethed.cancelDeferredTransactionById(txid,delayAccount1Address,delayAccount1Key, + // blockingStubFull); + + + Assert.assertTrue(deplayAccountBeforeBalance - deplayAccountAfterBalance + == delayTransactionFee + cancleDelayTransactionFee); + Assert.assertTrue(recevierAccountBeforeBalance == recevierAccountAfterDelayalance); + + } + + @Test(enabled = false, description = "Cancel deferred transaction") + public void test2CancleDeferredTransactionQuickly() { + //get account + ecKey = new ECKey(Utils.getRandom()); + delayAccount1Address = ecKey.getAddress(); + delayAccount1Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); + PublicMethed.printAddress(delayAccount1Key); + ecKey3 = new ECKey(Utils.getRandom()); + receiverAccountAddress = ecKey3.getAddress(); + receiverAccountKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); + PublicMethed.printAddress(receiverAccountKey); + + Assert.assertTrue(PublicMethed.sendcoin(delayAccount1Address, 100000000L,fromAddress, + testKey002, blockingStubFull)); + Assert.assertTrue(PublicMethed.sendcoin(receiverAccountAddress, 100L,fromAddress, + testKey002, blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + //Do delay send coin transaction. + Long delaySecond = 10L; + Long sendCoinAmount = 1000L; + + //Query balance before send coin. + Long deplayAccountBeforeBalance = PublicMethed.queryAccount(delayAccount1Address, + blockingStubFull).getBalance(); + Long recevierAccountBeforeBalance = PublicMethed.queryAccount(receiverAccountAddress, + blockingStubFull).getBalance(); + logger.info("deplayAccountBeforeBalance " + deplayAccountBeforeBalance); + logger.info("recevierAccountBeforeBalance " + recevierAccountBeforeBalance); + String txid = PublicMethed.sendcoinDelayedGetTxid(receiverAccountAddress, sendCoinAmount, + delaySecond,delayAccount1Address, + delayAccount1Key, blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + Assert.assertFalse(PublicMethed.cancelDeferredTransactionById(txid,receiverAccountAddress, + receiverAccountKey,blockingStubFull)); + Assert.assertTrue(PublicMethed.cancelDeferredTransactionById(txid,delayAccount1Address, + delayAccount1Key,blockingStubFull)); + Assert.assertFalse(PublicMethed.cancelDeferredTransactionById(txid,delayAccount1Address, + delayAccount1Key,blockingStubFull)); + //PublicMethed.waitProduceNextBlock(blockingStubFull); + + Long deplayAccountAfterBalance = PublicMethed.queryAccount(delayAccount1Address, + blockingStubFull).getBalance(); + Long recevierAccountAfterDelayalance = PublicMethed.queryAccount(receiverAccountAddress, + blockingStubFull).getBalance(); + logger.info("deplayAccountAfterBalance " + deplayAccountAfterBalance); + logger.info("recevierAccountAfterDelayalance " + recevierAccountAfterDelayalance); + Assert.assertFalse(PublicMethed.cancelDeferredTransactionById(txid,delayAccount1Address, + delayAccount1Key,blockingStubFull)); + + + Assert.assertTrue(deplayAccountBeforeBalance - deplayAccountAfterBalance + == delayTransactionFee + cancleDelayTransactionFee); + Assert.assertTrue(recevierAccountBeforeBalance == recevierAccountAfterDelayalance); + + + } + + + /** + * constructor. + */ + + @AfterClass(enabled = false) + public void shutdown() throws InterruptedException { + if (channelFull != null) { + channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); + } + } +} + + diff --git a/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction003.java b/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction003.java new file mode 100644 index 00000000000..7d914804fb7 --- /dev/null +++ b/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction003.java @@ -0,0 +1,216 @@ +package stest.tron.wallet.dailybuild.delaytransaction; + +import com.google.protobuf.ByteString; +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import java.util.Optional; +import java.util.concurrent.TimeUnit; +import lombok.extern.slf4j.Slf4j; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeSuite; +import org.testng.annotations.Test; +import org.tron.api.WalletGrpc; +import org.tron.common.crypto.ECKey; +import org.tron.common.crypto.Hash; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.Utils; +import org.tron.core.Wallet; +import org.tron.protos.Protocol.Account; +//import org.tron.protos.Protocol.DeferredTransaction; +import org.tron.protos.Protocol.Transaction; +import org.tron.protos.Protocol.TransactionInfo; +import stest.tron.wallet.common.client.Configuration; +import stest.tron.wallet.common.client.Parameter.CommonConstant; +import stest.tron.wallet.common.client.utils.PublicMethed; +import stest.tron.wallet.common.client.utils.Sha256Hash; + +@Slf4j +public class DelayTransaction003 { + + private final String testKey002 = Configuration.getByPath("testng.conf") + .getString("foundationAccount.key1"); + private final String testKey003 = Configuration.getByPath("testng.conf") + .getString("foundationAccount.key2"); + private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); + private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); + + private ManagedChannel channelFull = null; + private WalletGrpc.WalletBlockingStub blockingStubFull = null; + private static final long now = System.currentTimeMillis(); + private static final long totalSupply = now; + private static final String name = "Asset008_" + Long.toString(now); + String description = "just-test"; + String url = "https://github.com/tronprotocol/wallet-cli/"; + Long delaySecond = 10L; + + private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") + .get(1); + private Long delayTransactionFee = Configuration.getByPath("testng.conf") + .getLong("defaultParameter.delayTransactionFee"); + private Long cancleDelayTransactionFee = Configuration.getByPath("testng.conf") + .getLong("defaultParameter.cancleDelayTransactionFee"); + ByteString assetId; + + + + Optional infoById = null; + //Optional deferredTransactionById = null; + Optional getTransactionById = null; + + + ECKey ecKey = new ECKey(Utils.getRandom()); + byte[] assetOwnerAddress = ecKey.getAddress(); + String assetOwnerKey = ByteArray.toHexString(ecKey.getPrivKeyBytes()); + + ECKey ecKey3 = new ECKey(Utils.getRandom()); + byte[] receiverAssetAddress = ecKey3.getAddress(); + String receiverassetKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); + + + @BeforeSuite + public void beforeSuite() { + Wallet wallet = new Wallet(); + Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); + } + + /** + * constructor. + */ + + @BeforeClass(enabled = false) + public void beforeClass() { + channelFull = ManagedChannelBuilder.forTarget(fullnode) + .usePlaintext(true) + .build(); + blockingStubFull = WalletGrpc.newBlockingStub(channelFull); + } + + @Test(enabled = false, description = "Delay transfer asset") + public void test1DelayTransferAsset() { + //get account + ecKey = new ECKey(Utils.getRandom()); + assetOwnerAddress = ecKey.getAddress(); + assetOwnerKey = ByteArray.toHexString(ecKey.getPrivKeyBytes()); + PublicMethed.printAddress(assetOwnerKey); + ecKey3 = new ECKey(Utils.getRandom()); + receiverAssetAddress = ecKey3.getAddress(); + receiverassetKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); + PublicMethed.printAddress(receiverassetKey); + + Assert.assertTrue(PublicMethed.sendcoin(assetOwnerAddress, 2048000000, fromAddress, + testKey002, blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + //Create test token. + Long start = System.currentTimeMillis() + 2000; + Long end = System.currentTimeMillis() + 1000000000; + Assert.assertTrue(PublicMethed.createAssetIssue(assetOwnerAddress, + name, totalSupply, 1, 1, start, end, 1, description, url, + 2000L, 2000L, 100000L, 1L, + assetOwnerKey, blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + Account assetOwnerAccount = PublicMethed.queryAccount(assetOwnerKey, blockingStubFull); + assetId = assetOwnerAccount.getAssetIssuedID(); + + //Delay transfer asset + Long transferAssetAmount = 1L; + final Long ownerAssetBalanceOfbeforeTransferAsset = PublicMethed + .getAssetBalanceByAssetId(assetId, assetOwnerKey,blockingStubFull); + final Long receiverAssetBalanceOfbeforeTransferAsset = PublicMethed + .getAssetBalanceByAssetId(assetId,receiverassetKey,blockingStubFull); + Assert.assertTrue(PublicMethed.transferAssetDelay(receiverAssetAddress, assetId.toByteArray(), + transferAssetAmount, delaySecond,assetOwnerAddress, assetOwnerKey, blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + Long ownerAssetBalanceInDelayTransferAsset = PublicMethed + .getAssetBalanceByAssetId(assetId,assetOwnerKey,blockingStubFull); + final Long receiverAssetBalanceInDelayTransferAsset = PublicMethed + .getAssetBalanceByAssetId(assetId,receiverassetKey,blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + Long ownerAssetBalanceAfterTransferAsset = PublicMethed + .getAssetBalanceByAssetId(assetId,assetOwnerKey,blockingStubFull); + Long receiverAssetBalanceAfterTransferAsset = PublicMethed + .getAssetBalanceByAssetId(assetId,receiverassetKey,blockingStubFull); + + + Assert.assertEquals(ownerAssetBalanceOfbeforeTransferAsset, + ownerAssetBalanceInDelayTransferAsset); + Assert.assertTrue(receiverAssetBalanceOfbeforeTransferAsset + == receiverAssetBalanceInDelayTransferAsset); + Assert.assertTrue(ownerAssetBalanceInDelayTransferAsset - transferAssetAmount + == ownerAssetBalanceAfterTransferAsset); + Assert.assertTrue(receiverAssetBalanceAfterTransferAsset == transferAssetAmount); + + } + + + @Test(enabled = false, description = "Cancel delay transfer asset") + public void test2CancelDelayTransferAsset() { + + + //Delay transfer asset + Long transferAssetAmount = 1L; + final Long ownerAssetBalanceOfbeforeTransferAsset = PublicMethed + .getAssetBalanceByAssetId(assetId, assetOwnerKey,blockingStubFull); + final Long receiverAssetBalanceOfbeforeTransferAsset = PublicMethed + .getAssetBalanceByAssetId(assetId,receiverassetKey,blockingStubFull); + + String txid = PublicMethed.transferAssetDelayGetTxid(receiverAssetAddress, + assetId.toByteArray(), transferAssetAmount, delaySecond,assetOwnerAddress, assetOwnerKey, + blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + //Assert.assertFalse(PublicMethed.cancelDeferredTransactionById(txid,receiverAssetAddress, + // receiverassetKey,blockingStubFull)); + Assert.assertTrue(PublicMethed.cancelDeferredTransactionById(txid,assetOwnerAddress, + assetOwnerKey,blockingStubFull)); + //Assert.assertFalse(PublicMethed.cancelDeferredTransactionById(txid,assetOwnerAddress, + // assetOwnerKey,blockingStubFull)); + + PublicMethed.waitProduceNextBlock(blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + Long ownerAssetBalanceAfterTransferAsset = PublicMethed + .getAssetBalanceByAssetId(assetId,assetOwnerKey,blockingStubFull); + Long receiverAssetBalanceAfterTransferAsset = PublicMethed + .getAssetBalanceByAssetId(assetId,receiverassetKey,blockingStubFull); + + + Assert.assertEquals(ownerAssetBalanceOfbeforeTransferAsset, ownerAssetBalanceAfterTransferAsset + ); + Assert.assertTrue(receiverAssetBalanceAfterTransferAsset + == receiverAssetBalanceOfbeforeTransferAsset); + Assert.assertFalse(PublicMethed.cancelDeferredTransactionById(txid,assetOwnerAddress, + assetOwnerKey,blockingStubFull)); + + } + + @Test(enabled = false, description = "Delay unfreeze asset") + public void test3DelayUnfreezeAsset() { + + final Long ownerAssetBalanceOfbeforeTransferAsset = PublicMethed + .getAssetBalanceByAssetId(assetId, assetOwnerKey,blockingStubFull); + + String txid = PublicMethed.unfreezeAssetDelayGetTxid(assetOwnerAddress,delaySecond, + assetOwnerKey,blockingStubFull); + + + + } + + + + + /** + * constructor. + */ + + @AfterClass(enabled = false) + public void shutdown() throws InterruptedException { + if (channelFull != null) { + channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); + } + } +} + + diff --git a/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction004.java b/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction004.java new file mode 100644 index 00000000000..5134a548d9a --- /dev/null +++ b/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction004.java @@ -0,0 +1,199 @@ +package stest.tron.wallet.dailybuild.delaytransaction; + +import com.google.protobuf.ByteString; +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import java.util.Optional; +import java.util.concurrent.TimeUnit; +import lombok.extern.slf4j.Slf4j; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeSuite; +import org.testng.annotations.Test; +import org.tron.api.WalletGrpc; +import org.tron.common.crypto.ECKey; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.Utils; +import org.tron.core.Wallet; +import org.tron.protos.Protocol.Account; +//import org.tron.protos.Protocol.DeferredTransaction; +import org.tron.protos.Protocol.SmartContract; +import org.tron.protos.Protocol.Transaction; +import org.tron.protos.Protocol.TransactionInfo; +import stest.tron.wallet.common.client.Configuration; +import stest.tron.wallet.common.client.Parameter.CommonConstant; +import stest.tron.wallet.common.client.utils.PublicMethed; + +@Slf4j +public class DelayTransaction004 { + + private final String testKey002 = Configuration.getByPath("testng.conf") + .getString("foundationAccount.key1"); + private final String testKey003 = Configuration.getByPath("testng.conf") + .getString("foundationAccount.key2"); + private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); + private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); + + private ManagedChannel channelFull = null; + private WalletGrpc.WalletBlockingStub blockingStubFull = null; + private static final long now = System.currentTimeMillis(); + Long delaySecond = 10L; + + private long maxFeeLimit = Configuration.getByPath("testng.conf") + .getLong("defaultParameter.maxFeeLimit"); + + private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") + .get(1); + private Long delayTransactionFee = Configuration.getByPath("testng.conf") + .getLong("defaultParameter.delayTransactionFee"); + private Long cancleDelayTransactionFee = Configuration.getByPath("testng.conf") + .getLong("defaultParameter.cancleDelayTransactionFee"); + ByteString assetId; + private byte[] contractAddress = null; + SmartContract smartContract; + + ECKey ecKey = new ECKey(Utils.getRandom()); + byte[] smartContractOwnerAddress = ecKey.getAddress(); + String smartContractOwnerKey = ByteArray.toHexString(ecKey.getPrivKeyBytes()); + + @BeforeSuite + public void beforeSuite() { + Wallet wallet = new Wallet(); + Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); + } + + /** + * constructor. + */ + + @BeforeClass(enabled = false) + public void beforeClass() { + channelFull = ManagedChannelBuilder.forTarget(fullnode) + .usePlaintext(true) + .build(); + blockingStubFull = WalletGrpc.newBlockingStub(channelFull); + } + + @Test(enabled = false, description = "Delay update setting contract") + public void test1DelayUpdateSetting() { + //get account + ecKey = new ECKey(Utils.getRandom()); + smartContractOwnerAddress = ecKey.getAddress(); + smartContractOwnerKey = ByteArray.toHexString(ecKey.getPrivKeyBytes()); + PublicMethed.printAddress(smartContractOwnerKey); + + + Assert.assertTrue(PublicMethed.sendcoin(smartContractOwnerAddress, 2048000000, fromAddress, + testKey002, blockingStubFull)); + //PublicMethed.freezeBalance(smartContractOwnerAddress,10000000L,3, + // smartContractOwnerKey,blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + String contractName = "TRONTOKEN"; + String code = Configuration.getByPath("testng.conf") + .getString("code.code_ContractScenario004_deployErc20TronToken"); + String abi = Configuration.getByPath("testng.conf") + .getString("abi.abi_ContractScenario004_deployErc20TronToken"); + contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, + 0L, 100, 999L,"0",0,null, + smartContractOwnerKey, smartContractOwnerAddress, blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); + Long oldContractPercent = smartContract.getConsumeUserResourcePercent(); + Assert.assertTrue(PublicMethed.updateSetting(contractAddress,oldContractPercent, + smartContractOwnerKey,smartContractOwnerAddress,blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); + Assert.assertTrue(smartContract.getConsumeUserResourcePercent() == oldContractPercent); + + Long newContractPercent = 39L; + final String txid = PublicMethed.updateSettingDelayGetTxid(contractAddress,newContractPercent, + delaySecond,smartContractOwnerKey,smartContractOwnerAddress,blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); + Assert.assertTrue(smartContract.getConsumeUserResourcePercent() == oldContractPercent); + PublicMethed.waitProduceNextBlock(blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); + logger.info("newContractPercent: " + smartContract.getConsumeUserResourcePercent()); + Assert.assertTrue(smartContract.getConsumeUserResourcePercent() == newContractPercent); + + Long netFee = PublicMethed.getTransactionInfoById(txid,blockingStubFull).get().getReceipt() + .getNetFee(); + Long fee = PublicMethed.getTransactionInfoById(txid,blockingStubFull).get().getFee(); + Assert.assertTrue(fee - netFee == delayTransactionFee); + Long afterFreeNetUsaged = PublicMethed.queryAccount(smartContractOwnerKey, + blockingStubFull).getFreeNetUsage(); + Long beforeFreeNetUsaged = PublicMethed.queryAccount(smartContractOwnerKey, + blockingStubFull).getFreeNetUsage(); + Long inDelayFreeNetUsaged = PublicMethed.queryAccount(smartContractOwnerKey, + blockingStubFull).getFreeNetUsage(); + logger.info("beforeFreeNetUsaged: " + beforeFreeNetUsaged); + logger.info("inDelayFreeNetUsaged: " + inDelayFreeNetUsaged); + logger.info("afterFreeNetUsaged: " + afterFreeNetUsaged); + Assert.assertTrue(beforeFreeNetUsaged + 50 < inDelayFreeNetUsaged); + Assert.assertTrue(inDelayFreeNetUsaged + 50 < afterFreeNetUsaged); + + } + + @Test(enabled = false, description = "Cancel delay update setting contract") + public void test2CancelDelayUpdateSetting() { + //get account + final Long oldContractPercent = smartContract.getConsumeUserResourcePercent(); + final Long newContractPercent = 46L; + + String txid = PublicMethed.updateSettingDelayGetTxid(contractAddress,newContractPercent, + delaySecond,smartContractOwnerKey,smartContractOwnerAddress,blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + Account ownerAccount = PublicMethed.queryAccount(smartContractOwnerKey,blockingStubFull); + final Long beforeCancelBalance = ownerAccount.getBalance(); + + + Assert.assertFalse(PublicMethed.cancelDeferredTransactionById(txid,fromAddress,testKey002, + blockingStubFull)); + final String cancelTxid = PublicMethed.cancelDeferredTransactionByIdGetTxid(txid, + smartContractOwnerAddress,smartContractOwnerKey,blockingStubFull); + Assert.assertFalse(PublicMethed.cancelDeferredTransactionById(txid,smartContractOwnerAddress, + smartContractOwnerKey,blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); + logger.info("newContractPercent: " + smartContract.getConsumeUserResourcePercent()); + Assert.assertTrue(smartContract.getConsumeUserResourcePercent() == oldContractPercent); + + final Long netFee = PublicMethed.getTransactionInfoById(cancelTxid,blockingStubFull).get() + .getReceipt().getNetFee(); + final Long fee = PublicMethed.getTransactionInfoById(cancelTxid,blockingStubFull).get() + .getFee(); + logger.info("net fee : " + PublicMethed.getTransactionInfoById(cancelTxid,blockingStubFull) + .get().getReceipt().getNetFee()); + logger.info("Fee : " + PublicMethed.getTransactionInfoById(cancelTxid,blockingStubFull) + .get().getFee()); + + ownerAccount = PublicMethed.queryAccount(smartContractOwnerKey,blockingStubFull); + Long afterCancelBalance = ownerAccount.getBalance(); + Assert.assertTrue(fee - netFee == cancleDelayTransactionFee); + Assert.assertTrue(fee == beforeCancelBalance - afterCancelBalance); + + logger.info("beforeCancelBalance: " + beforeCancelBalance); + logger.info("afterCancelBalance : " + afterCancelBalance); + } + + + + + + /** + * constructor. + */ + + @AfterClass(enabled = false) + public void shutdown() throws InterruptedException { + if (channelFull != null) { + channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); + } + } +} + + diff --git a/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction005.java b/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction005.java new file mode 100644 index 00000000000..76a9220cc68 --- /dev/null +++ b/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction005.java @@ -0,0 +1,181 @@ +package stest.tron.wallet.dailybuild.delaytransaction; + +import com.google.protobuf.ByteString; +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import java.util.concurrent.TimeUnit; +import lombok.extern.slf4j.Slf4j; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeSuite; +import org.testng.annotations.Test; +import org.tron.api.WalletGrpc; +import org.tron.common.crypto.ECKey; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.Utils; +import org.tron.core.Wallet; +import org.tron.protos.Protocol.Account; +import org.tron.protos.Protocol.SmartContract; +import stest.tron.wallet.common.client.Configuration; +import stest.tron.wallet.common.client.Parameter.CommonConstant; +import stest.tron.wallet.common.client.utils.PublicMethed; + +@Slf4j +public class DelayTransaction005 { + + private final String testKey002 = Configuration.getByPath("testng.conf") + .getString("foundationAccount.key1"); + private final String testKey003 = Configuration.getByPath("testng.conf") + .getString("foundationAccount.key2"); + private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); + private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); + + private ManagedChannel channelFull = null; + private WalletGrpc.WalletBlockingStub blockingStubFull = null; + private static final long now = System.currentTimeMillis(); + Long delaySecond = 10L; + + private long maxFeeLimit = Configuration.getByPath("testng.conf") + .getLong("defaultParameter.maxFeeLimit"); + + private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") + .get(1); + private Long delayTransactionFee = Configuration.getByPath("testng.conf") + .getLong("defaultParameter.delayTransactionFee"); + private Long cancleDelayTransactionFee = Configuration.getByPath("testng.conf") + .getLong("defaultParameter.cancleDelayTransactionFee"); + ByteString assetId; + private byte[] contractAddress = null; + SmartContract smartContract; + + ECKey ecKey = new ECKey(Utils.getRandom()); + byte[] smartContractOwnerAddress = ecKey.getAddress(); + String smartContractOwnerKey = ByteArray.toHexString(ecKey.getPrivKeyBytes()); + + @BeforeSuite + public void beforeSuite() { + Wallet wallet = new Wallet(); + Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); + } + + /** + * constructor. + */ + + @BeforeClass(enabled = false) + public void beforeClass() { + channelFull = ManagedChannelBuilder.forTarget(fullnode) + .usePlaintext(true) + .build(); + blockingStubFull = WalletGrpc.newBlockingStub(channelFull); + } + + @Test(enabled = false, description = "Delay update energy limit contract") + public void test1DelayUpdateSetting() { + //get account + ecKey = new ECKey(Utils.getRandom()); + smartContractOwnerAddress = ecKey.getAddress(); + smartContractOwnerKey = ByteArray.toHexString(ecKey.getPrivKeyBytes()); + PublicMethed.printAddress(smartContractOwnerKey); + + + Assert.assertTrue(PublicMethed.sendcoin(smartContractOwnerAddress, 2048000000, fromAddress, + testKey002, blockingStubFull)); + PublicMethed.freezeBalance(smartContractOwnerAddress,10000000L,3, + smartContractOwnerKey,blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + String contractName = "TRONTOKEN"; + String code = Configuration.getByPath("testng.conf") + .getString("code.code_ContractScenario004_deployErc20TronToken"); + String abi = Configuration.getByPath("testng.conf") + .getString("abi.abi_ContractScenario004_deployErc20TronToken"); + contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, + 0L, 100, 999L,"0",0,null, + smartContractOwnerKey, smartContractOwnerAddress, blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); + Long oldOriginEnergyLimit = 567L; + Assert.assertTrue(PublicMethed.updateEnergyLimit(contractAddress,oldOriginEnergyLimit, + smartContractOwnerKey,smartContractOwnerAddress,blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); + Assert.assertTrue(smartContract.getOriginEnergyLimit() == oldOriginEnergyLimit); + + Long newOriginEnergyLimit = 8765L; + final String txid = PublicMethed.updateEnergyLimitDelayGetTxid(contractAddress, + newOriginEnergyLimit, delaySecond,smartContractOwnerKey,smartContractOwnerAddress, + blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); + Assert.assertTrue(smartContract.getOriginEnergyLimit() == oldOriginEnergyLimit); + PublicMethed.waitProduceNextBlock(blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); + logger.info("newOriginEnergyLimit: " + smartContract.getOriginEnergyLimit()); + Assert.assertTrue(smartContract.getOriginEnergyLimit() == newOriginEnergyLimit); + + Long netFee = PublicMethed.getTransactionInfoById(txid,blockingStubFull).get().getReceipt() + .getNetFee(); + Long fee = PublicMethed.getTransactionInfoById(txid,blockingStubFull).get().getFee(); + Assert.assertTrue(fee - netFee == delayTransactionFee); + + } + + @Test(enabled = false, description = "Cancel delay energy limit contract") + public void test2CancelDelayUpdateSetting() { + //get account + final Long oldOriginEnergyLimit = smartContract.getOriginEnergyLimit(); + final Long newOriginEnergyLimit = 466L; + + String txid = PublicMethed.updateEnergyLimitDelayGetTxid(contractAddress,newOriginEnergyLimit, + delaySecond,smartContractOwnerKey,smartContractOwnerAddress,blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + Account ownerAccount = PublicMethed.queryAccount(smartContractOwnerKey,blockingStubFull); + final Long beforeCancelBalance = ownerAccount.getBalance(); + + + Assert.assertFalse(PublicMethed.cancelDeferredTransactionById(txid,fromAddress,testKey002, + blockingStubFull)); + final String cancelTxid = PublicMethed.cancelDeferredTransactionByIdGetTxid(txid, + smartContractOwnerAddress,smartContractOwnerKey,blockingStubFull); + Assert.assertFalse(PublicMethed.cancelDeferredTransactionById(txid,smartContractOwnerAddress, + smartContractOwnerKey,blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + smartContract = PublicMethed.getContract(contractAddress, blockingStubFull); + logger.info("newOriginEnergyLimit: " + smartContract.getOriginEnergyLimit()); + Assert.assertTrue(smartContract.getOriginEnergyLimit() == oldOriginEnergyLimit); + + final Long netFee = PublicMethed.getTransactionInfoById(cancelTxid,blockingStubFull).get() + .getReceipt().getNetFee(); + final Long fee = PublicMethed.getTransactionInfoById(cancelTxid,blockingStubFull).get() + .getFee(); + logger.info("net fee : " + PublicMethed.getTransactionInfoById(cancelTxid,blockingStubFull) + .get().getReceipt().getNetFee()); + logger.info("Fee : " + PublicMethed.getTransactionInfoById(cancelTxid,blockingStubFull) + .get().getFee()); + + ownerAccount = PublicMethed.queryAccount(smartContractOwnerKey,blockingStubFull); + Long afterCancelBalance = ownerAccount.getBalance(); + Assert.assertTrue(fee - netFee == cancleDelayTransactionFee); + Assert.assertTrue(fee == beforeCancelBalance - afterCancelBalance); + + logger.info("beforeCancelBalance: " + beforeCancelBalance); + logger.info("afterCancelBalance : " + afterCancelBalance); + } + + /** + * constructor. + */ + + @AfterClass(enabled = false) + public void shutdown() throws InterruptedException { + if (channelFull != null) { + channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); + } + } +} + + diff --git a/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction006.java b/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction006.java new file mode 100644 index 00000000000..14e7122ae0e --- /dev/null +++ b/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction006.java @@ -0,0 +1,196 @@ +package stest.tron.wallet.dailybuild.delaytransaction; + +import com.google.protobuf.ByteString; +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import java.util.concurrent.TimeUnit; +import lombok.extern.slf4j.Slf4j; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeSuite; +import org.testng.annotations.Test; +import org.tron.api.WalletGrpc; +import org.tron.common.crypto.ECKey; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.Utils; +import org.tron.core.Wallet; +import org.tron.protos.Protocol.Account; +import org.tron.protos.Protocol.SmartContract; +import stest.tron.wallet.common.client.Configuration; +import stest.tron.wallet.common.client.Parameter.CommonConstant; +import stest.tron.wallet.common.client.utils.PublicMethed; + +@Slf4j +public class DelayTransaction006 { + + private final String testKey002 = Configuration.getByPath("testng.conf") + .getString("foundationAccount.key1"); + private final String testKey003 = Configuration.getByPath("testng.conf") + .getString("foundationAccount.key2"); + private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); + private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); + + private ManagedChannel channelFull = null; + private WalletGrpc.WalletBlockingStub blockingStubFull = null; + private static final long now = System.currentTimeMillis(); + private static final long totalSupply = now; + private static final String name = "Asset008_" + Long.toString(now); + String description = "just-test"; + String url = "https://github.com/tronprotocol/wallet-cli/"; + Long delaySecond = 10L; + + private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") + .get(1); + private Long delayTransactionFee = Configuration.getByPath("testng.conf") + .getLong("defaultParameter.delayTransactionFee"); + private Long cancleDelayTransactionFee = Configuration.getByPath("testng.conf") + .getLong("defaultParameter.cancleDelayTransactionFee"); + ByteString assetId; + private byte[] contractAddress = null; + SmartContract smartContract; + + ECKey ecKey = new ECKey(Utils.getRandom()); + byte[] assetOwnerAddress = ecKey.getAddress(); + String assetOwnerKey = ByteArray.toHexString(ecKey.getPrivKeyBytes()); + + @BeforeSuite + public void beforeSuite() { + Wallet wallet = new Wallet(); + Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); + } + + /** + * constructor. + */ + + @BeforeClass(enabled = false) + public void beforeClass() { + channelFull = ManagedChannelBuilder.forTarget(fullnode) + .usePlaintext(true) + .build(); + blockingStubFull = WalletGrpc.newBlockingStub(channelFull); + } + + @Test(enabled = false, description = "Delay update asset contract") + public void test1DelayUpdateSetting() { + //get account + ecKey = new ECKey(Utils.getRandom()); + assetOwnerAddress = ecKey.getAddress(); + assetOwnerKey = ByteArray.toHexString(ecKey.getPrivKeyBytes()); + PublicMethed.printAddress(assetOwnerKey); + + + Assert.assertTrue(PublicMethed.sendcoin(assetOwnerAddress, 2048000000, fromAddress, + testKey002, blockingStubFull)); + + final Long oldFreeAssetNetLimit = 2000L; + Long start = System.currentTimeMillis() + 2000; + Long end = System.currentTimeMillis() + 1000000000; + Assert.assertTrue(PublicMethed.createAssetIssue(assetOwnerAddress, + name, totalSupply, 1, 1, start, end, 1, description, url, + oldFreeAssetNetLimit, 2000L, 1L, 1L, + assetOwnerKey, blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + Account assetOwnerAccount = PublicMethed.queryAccount(assetOwnerKey, blockingStubFull); + assetId = assetOwnerAccount.getAssetIssuedID(); + String newAssetUrl = "new.url"; + String newAssetDescription = "new.description"; + + final Long newFreeAssetNetLimit = 3333L; + final String txid = PublicMethed.updateAssetDelay(assetOwnerAddress, + newAssetDescription.getBytes(), newAssetUrl.getBytes(),newFreeAssetNetLimit, + 23L,delaySecond,assetOwnerKey,blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + Assert.assertTrue(PublicMethed.getAssetIssueById(ByteArray.toStr(assetId + .toByteArray()),blockingStubFull).getFreeAssetNetLimit() == oldFreeAssetNetLimit); + PublicMethed.waitProduceNextBlock(blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + Assert.assertTrue(PublicMethed.getAssetIssueById(ByteArray.toStr(assetId + .toByteArray()),blockingStubFull).getFreeAssetNetLimit() == newFreeAssetNetLimit); + Long afterNetUsaged = PublicMethed.queryAccount(assetOwnerKey,blockingStubFull) + .getFreeNetUsage(); + Long netFee = PublicMethed.getTransactionInfoById(txid,blockingStubFull).get() + .getReceipt().getNetFee(); + Long fee = PublicMethed.getTransactionInfoById(txid,blockingStubFull).get().getFee(); + Long beforeNetUsaged = PublicMethed.queryAccount(assetOwnerKey,blockingStubFull) + .getFreeNetUsage(); + Long inDelayNetUsaged = PublicMethed.queryAccount(assetOwnerKey,blockingStubFull) + .getFreeNetUsage(); + Assert.assertTrue(fee - netFee == delayTransactionFee); + Assert.assertTrue(beforeNetUsaged + 50 < inDelayNetUsaged); + Assert.assertTrue(inDelayNetUsaged + 50 < afterNetUsaged); + + } + + @Test(enabled = false, description = "Cancel delay asset setting contract") + public void test2CancelDelayUpdateAsset() { + //get account + final Long oldFreeAssetNetLimit = PublicMethed.getAssetIssueById(assetId.toStringUtf8(), + blockingStubFull).getFreeAssetNetLimit(); + final Long newFreeAssetNetLimit = 461L; + + String newAssetUrl = "new.url"; + String newAssetDescription = "new.description"; + logger.info("Before delay net usage: " + PublicMethed.queryAccount(assetOwnerKey, + blockingStubFull).getFreeNetUsage()); + String txid = PublicMethed.updateAssetDelay(assetOwnerAddress,newAssetDescription.getBytes(), + newAssetUrl.getBytes(),newFreeAssetNetLimit,23L,delaySecond,assetOwnerKey, + blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + logger.info("In delay net usage: " + PublicMethed.queryAccount(assetOwnerKey,blockingStubFull) + .getFreeNetUsage()); + Assert.assertFalse(PublicMethed.cancelDeferredTransactionById(txid,fromAddress,testKey002, + blockingStubFull)); + final String cancelTxid = PublicMethed.cancelDeferredTransactionByIdGetTxid(txid, + assetOwnerAddress,assetOwnerKey,blockingStubFull); + Assert.assertFalse(PublicMethed.cancelDeferredTransactionById(txid,assetOwnerAddress, + assetOwnerKey,blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + logger.info("After cancle net usage: " + PublicMethed.queryAccount(assetOwnerKey, + blockingStubFull).getFreeNetUsage()); + + Assert.assertTrue(PublicMethed.getAssetIssueById(assetId.toStringUtf8(), + blockingStubFull).getFreeAssetNetLimit() == oldFreeAssetNetLimit); + + final Long netFee = PublicMethed.getTransactionInfoById(cancelTxid,blockingStubFull).get() + .getReceipt().getNetFee(); + final Long fee = PublicMethed.getTransactionInfoById(cancelTxid,blockingStubFull).get() + .getFee(); + logger.info("net fee : " + PublicMethed.getTransactionInfoById(cancelTxid,blockingStubFull) + .get().getReceipt().getNetFee()); + logger.info("Fee : " + PublicMethed.getTransactionInfoById(cancelTxid,blockingStubFull) + .get().getFee()); + + Assert.assertTrue(fee - netFee == cancleDelayTransactionFee); + + Long afterNetUsaged = PublicMethed.queryAccount(assetOwnerKey,blockingStubFull) + .getFreeNetUsage(); + Long beforeNetUsaged = PublicMethed.queryAccount(assetOwnerKey,blockingStubFull) + .getFreeNetUsage(); + + logger.info("beforeNetUsaged: " + beforeNetUsaged); + logger.info("afterNetUsaged: " + afterNetUsaged); + Assert.assertTrue(beforeNetUsaged >= afterNetUsaged); + + } + + + + + + /** + * constructor. + */ + + @AfterClass(enabled = false) + public void shutdown() throws InterruptedException { + if (channelFull != null) { + channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); + } + } +} + + diff --git a/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction007.java b/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction007.java new file mode 100644 index 00000000000..a045d8f106a --- /dev/null +++ b/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction007.java @@ -0,0 +1,175 @@ +package stest.tron.wallet.dailybuild.delaytransaction; + +import com.google.protobuf.ByteString; +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import java.util.concurrent.TimeUnit; +import lombok.extern.slf4j.Slf4j; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeSuite; +import org.testng.annotations.Test; +import org.tron.api.WalletGrpc; +import org.tron.common.crypto.ECKey; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.Utils; +import org.tron.core.Wallet; +import org.tron.protos.Protocol.Account; +import org.tron.protos.Protocol.SmartContract; +import stest.tron.wallet.common.client.Configuration; +import stest.tron.wallet.common.client.Parameter.CommonConstant; +import stest.tron.wallet.common.client.utils.PublicMethed; + +@Slf4j +public class DelayTransaction007 { + + private final String testKey002 = Configuration.getByPath("testng.conf") + .getString("foundationAccount.key1"); + private final String testKey003 = Configuration.getByPath("testng.conf") + .getString("foundationAccount.key2"); + private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); + private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); + + private ManagedChannel channelFull = null; + private WalletGrpc.WalletBlockingStub blockingStubFull = null; + private static final long now = System.currentTimeMillis(); + private static final long totalSupply = now; + private static final String name = "Asset008_" + Long.toString(now); + String description = "just-test"; + String url = "https://github.com/tronprotocol/wallet-cli/"; + Long delaySecond = 10L; + + private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") + .get(0); + private Long delayTransactionFee = Configuration.getByPath("testng.conf") + .getLong("defaultParameter.delayTransactionFee"); + private Long cancleDelayTransactionFee = Configuration.getByPath("testng.conf") + .getLong("defaultParameter.cancleDelayTransactionFee"); + ByteString assetId; + private byte[] contractAddress = null; + SmartContract smartContract; + + ECKey ecKey = new ECKey(Utils.getRandom()); + byte[] doCreateAccountAddress = ecKey.getAddress(); + String doCreateAccountKey = ByteArray.toHexString(ecKey.getPrivKeyBytes()); + + ECKey ecKey1 = new ECKey(Utils.getRandom()); + byte[] newAccountAddress = ecKey1.getAddress(); + String newAccountKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); + + @BeforeSuite + public void beforeSuite() { + Wallet wallet = new Wallet(); + Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); + } + + /** + * constructor. + */ + + @BeforeClass(enabled = false) + public void beforeClass() { + channelFull = ManagedChannelBuilder.forTarget(fullnode) + .usePlaintext(true) + .build(); + blockingStubFull = WalletGrpc.newBlockingStub(channelFull); + } + + @Test(enabled = false, description = "Delay account create contract") + public void test1DelayAccountCreate() { + //get account + ecKey = new ECKey(Utils.getRandom()); + doCreateAccountAddress = ecKey.getAddress(); + doCreateAccountKey = ByteArray.toHexString(ecKey.getPrivKeyBytes()); + PublicMethed.printAddress(doCreateAccountKey); + + ecKey1 = new ECKey(Utils.getRandom()); + newAccountAddress = ecKey1.getAddress(); + newAccountKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); + PublicMethed.printAddress(newAccountKey); + + Assert.assertTrue(PublicMethed.sendcoin(doCreateAccountAddress, 1000000L, fromAddress, + testKey002, blockingStubFull)); + + + Long beforeCreateAccountBalance = PublicMethed.queryAccount(doCreateAccountKey, + blockingStubFull).getBalance(); + final String txid = PublicMethed.createAccountDelayGetTxid(doCreateAccountAddress, + newAccountAddress,delaySecond,doCreateAccountKey,blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + Assert.assertTrue(PublicMethed.queryAccount(newAccountAddress,blockingStubFull) + .getCreateTime() == 0); + Long balanceInDelay = PublicMethed.queryAccount(doCreateAccountKey,blockingStubFull) + .getBalance(); + Assert.assertTrue(beforeCreateAccountBalance - balanceInDelay == delayTransactionFee); + PublicMethed.waitProduceNextBlock(blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + logger.info("create time is " + PublicMethed.queryAccount(newAccountAddress,blockingStubFull) + .getCreateTime()); + Assert.assertTrue(PublicMethed.queryAccount(newAccountAddress,blockingStubFull) + .getCreateTime() > 0); + Long afterCreateAccountBalance = PublicMethed.queryAccount(doCreateAccountKey,blockingStubFull) + .getBalance(); + Long netFee = PublicMethed.getTransactionInfoById(txid,blockingStubFull).get().getReceipt() + .getNetFee(); + Long fee = PublicMethed.getTransactionInfoById(txid,blockingStubFull).get().getFee(); + Assert.assertTrue(fee - netFee == delayTransactionFee); + Assert.assertTrue(beforeCreateAccountBalance - afterCreateAccountBalance + == delayTransactionFee + 100000L); + + } + + @Test(enabled = false, description = "Cancel delay account create contract") + public void test2CancelDelayUpdateSetting() { + ecKey1 = new ECKey(Utils.getRandom()); + newAccountAddress = ecKey1.getAddress(); + newAccountKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); + PublicMethed.printAddress(newAccountKey); + + final Long beforeCreateBalance = PublicMethed.queryAccount(doCreateAccountKey,blockingStubFull) + .getBalance(); + final String txid = PublicMethed.createAccountDelayGetTxid(doCreateAccountAddress, + newAccountAddress,delaySecond,doCreateAccountKey,blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + Assert.assertFalse(PublicMethed.cancelDeferredTransactionById(txid,fromAddress,testKey002, + blockingStubFull)); + final String cancelTxid = PublicMethed.cancelDeferredTransactionByIdGetTxid(txid, + doCreateAccountAddress,doCreateAccountKey,blockingStubFull); + Assert.assertFalse(PublicMethed.cancelDeferredTransactionById(txid,doCreateAccountAddress, + doCreateAccountKey,blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + final Long afterCreateBalance = PublicMethed.queryAccount(doCreateAccountKey,blockingStubFull) + .getBalance(); + final Long netFee = PublicMethed.getTransactionInfoById(cancelTxid,blockingStubFull).get() + .getReceipt().getNetFee(); + final Long fee = PublicMethed.getTransactionInfoById(cancelTxid,blockingStubFull).get() + .getFee(); + logger.info("net fee : " + PublicMethed.getTransactionInfoById(cancelTxid,blockingStubFull) + .get().getReceipt().getNetFee()); + logger.info("Fee : " + PublicMethed.getTransactionInfoById(cancelTxid,blockingStubFull) + .get().getFee()); + + Assert.assertTrue(fee - netFee == cancleDelayTransactionFee + delayTransactionFee); + Assert.assertTrue(beforeCreateBalance - afterCreateBalance + == cancleDelayTransactionFee + delayTransactionFee); + + } + + + /** + * constructor. + */ + + @AfterClass(enabled = false) + public void shutdown() throws InterruptedException { + if (channelFull != null) { + channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); + } + } +} + + diff --git a/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction008.java b/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction008.java new file mode 100644 index 00000000000..37310967ef9 --- /dev/null +++ b/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction008.java @@ -0,0 +1,179 @@ +package stest.tron.wallet.dailybuild.delaytransaction; + +import com.google.protobuf.ByteString; +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import java.nio.charset.Charset; +import java.util.concurrent.TimeUnit; +import lombok.extern.slf4j.Slf4j; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeSuite; +import org.testng.annotations.Test; +import org.tron.api.WalletGrpc; +import org.tron.common.crypto.ECKey; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.Utils; +import org.tron.core.Wallet; +import org.tron.protos.Protocol.SmartContract; +import stest.tron.wallet.common.client.Configuration; +import stest.tron.wallet.common.client.Parameter.CommonConstant; +import stest.tron.wallet.common.client.utils.PublicMethed; + +@Slf4j +public class DelayTransaction008 { + + private final String testKey002 = Configuration.getByPath("testng.conf") + .getString("foundationAccount.key1"); + private final String testKey003 = Configuration.getByPath("testng.conf") + .getString("foundationAccount.key2"); + private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); + private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); + + private ManagedChannel channelFull = null; + private WalletGrpc.WalletBlockingStub blockingStubFull = null; + private static final long now = System.currentTimeMillis(); + private static final long totalSupply = now; + private static final String name = "Asset008_" + Long.toString(now); + String description = "just-test"; + String url = "https://github.com/tronprotocol/wallet-cli/"; + Long delaySecond = 10L; + private static String updateAccountName; + + private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") + .get(0); + private Long delayTransactionFee = Configuration.getByPath("testng.conf") + .getLong("defaultParameter.delayTransactionFee"); + private Long cancleDelayTransactionFee = Configuration.getByPath("testng.conf") + .getLong("defaultParameter.cancleDelayTransactionFee"); + ByteString assetId; + private byte[] contractAddress = null; + SmartContract smartContract; + + ECKey ecKey = new ECKey(Utils.getRandom()); + byte[] doUpdateAccountAddress = ecKey.getAddress(); + String doUpdateAccountKey = ByteArray.toHexString(ecKey.getPrivKeyBytes()); + + ECKey ecKey1 = new ECKey(Utils.getRandom()); + byte[] newAccountAddress = ecKey1.getAddress(); + String newAccountKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); + + @BeforeSuite + public void beforeSuite() { + Wallet wallet = new Wallet(); + Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); + } + + /** + * constructor. + */ + + @BeforeClass(enabled = false) + public void beforeClass() { + channelFull = ManagedChannelBuilder.forTarget(fullnode) + .usePlaintext(true) + .build(); + blockingStubFull = WalletGrpc.newBlockingStub(channelFull); + } + + @Test(enabled = false, description = "Delay account update contract") + public void test1DelayAccountUpdate() { + //get account + ecKey = new ECKey(Utils.getRandom()); + doUpdateAccountAddress = ecKey.getAddress(); + doUpdateAccountKey = ByteArray.toHexString(ecKey.getPrivKeyBytes()); + PublicMethed.printAddress(doUpdateAccountKey); + + Assert.assertTrue(PublicMethed.sendcoin(doUpdateAccountAddress, 1000000L, fromAddress, + testKey002, blockingStubFull)); + + final Long beforeUpdateAccountBalance = PublicMethed.queryAccount(doUpdateAccountKey, + blockingStubFull).getBalance(); + updateAccountName = "account_" + Long.toString(System.currentTimeMillis()); + byte[] accountNameBytes = ByteArray.fromString(updateAccountName); + final String txid = PublicMethed.updateAccountDelayGetTxid(doUpdateAccountAddress, + accountNameBytes,delaySecond,doUpdateAccountKey,blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + String accountName = new String(PublicMethed.queryAccount(doUpdateAccountKey, + blockingStubFull).getAccountName().toByteArray(), Charset.forName("UTF-8")); + Assert.assertTrue(accountName.isEmpty()); + Assert.assertTrue(PublicMethed.queryAccount(newAccountAddress,blockingStubFull) + .getAccountName().isEmpty()); + Long balanceInDelay = PublicMethed.queryAccount(doUpdateAccountKey,blockingStubFull) + .getBalance(); + Assert.assertTrue(beforeUpdateAccountBalance - balanceInDelay == delayTransactionFee); + PublicMethed.waitProduceNextBlock(blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + accountName = new String(PublicMethed.queryAccount(doUpdateAccountKey,blockingStubFull) + .getAccountName().toByteArray(), Charset.forName("UTF-8")); + logger.info(accountName); + Assert.assertTrue(accountName.equalsIgnoreCase(updateAccountName)); + Long afterCreateAccountBalance = PublicMethed.queryAccount(doUpdateAccountKey,blockingStubFull) + .getBalance(); + Long netFee = PublicMethed.getTransactionInfoById(txid,blockingStubFull).get().getReceipt() + .getNetFee(); + Long fee = PublicMethed.getTransactionInfoById(txid,blockingStubFull).get().getFee(); + Assert.assertTrue(fee - netFee == delayTransactionFee); + Assert.assertTrue(beforeUpdateAccountBalance - afterCreateAccountBalance + == delayTransactionFee); + + } + + @Test(enabled = false, description = "Cancel delay account update contract") + public void test2CancelDelayUpdateAccount() { + //get account + ecKey = new ECKey(Utils.getRandom()); + doUpdateAccountAddress = ecKey.getAddress(); + doUpdateAccountKey = ByteArray.toHexString(ecKey.getPrivKeyBytes()); + PublicMethed.printAddress(doUpdateAccountKey); + + final Long beforeUpdateAccountBalance = PublicMethed.queryAccount(doUpdateAccountKey, + blockingStubFull).getBalance(); + updateAccountName = "account_" + Long.toString(System.currentTimeMillis()); + byte[] accountNameBytes = ByteArray.fromString(updateAccountName); + final String txid = PublicMethed.updateAccountDelayGetTxid(doUpdateAccountAddress, + accountNameBytes,delaySecond,doUpdateAccountKey,blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + Assert.assertFalse(PublicMethed.cancelDeferredTransactionById(txid,fromAddress,testKey002, + blockingStubFull)); + final String cancelTxid = PublicMethed.cancelDeferredTransactionByIdGetTxid(txid, + doUpdateAccountAddress,doUpdateAccountKey,blockingStubFull); + Assert.assertFalse(PublicMethed.cancelDeferredTransactionById(txid,doUpdateAccountAddress, + doUpdateAccountKey,blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + final Long afterUpdateBalance = PublicMethed.queryAccount(doUpdateAccountKey,blockingStubFull) + .getBalance(); + final Long netFee = PublicMethed.getTransactionInfoById(cancelTxid,blockingStubFull).get() + .getReceipt().getNetFee(); + final Long fee = PublicMethed.getTransactionInfoById(cancelTxid,blockingStubFull).get() + .getFee(); + logger.info("net fee : " + PublicMethed.getTransactionInfoById(cancelTxid,blockingStubFull) + .get().getReceipt().getNetFee()); + logger.info("Fee : " + PublicMethed.getTransactionInfoById(cancelTxid,blockingStubFull) + .get().getFee()); + + Assert.assertTrue(fee - netFee == cancleDelayTransactionFee); + Assert.assertTrue(beforeUpdateAccountBalance - afterUpdateBalance + == cancleDelayTransactionFee + delayTransactionFee); + + } + + + /** + * constructor. + */ + + @AfterClass(enabled = false) + public void shutdown() throws InterruptedException { + if (channelFull != null) { + channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); + } + } +} + + diff --git a/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction009.java b/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction009.java new file mode 100644 index 00000000000..70de6066642 --- /dev/null +++ b/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction009.java @@ -0,0 +1,184 @@ +package stest.tron.wallet.dailybuild.delaytransaction; + +import com.google.protobuf.ByteString; +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import java.nio.charset.Charset; +import java.util.concurrent.TimeUnit; +import lombok.extern.slf4j.Slf4j; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeSuite; +import org.testng.annotations.Test; +import org.tron.api.WalletGrpc; +import org.tron.common.crypto.ECKey; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.Utils; +import org.tron.core.Wallet; +import org.tron.protos.Protocol.SmartContract; +import stest.tron.wallet.common.client.Configuration; +import stest.tron.wallet.common.client.Parameter.CommonConstant; +import stest.tron.wallet.common.client.utils.PublicMethed; + +@Slf4j +public class DelayTransaction009 { + + private final String testKey002 = Configuration.getByPath("testng.conf") + .getString("foundationAccount.key1"); + private final String testKey003 = Configuration.getByPath("testng.conf") + .getString("foundationAccount.key2"); + private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); + private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); + + private ManagedChannel channelFull = null; + private WalletGrpc.WalletBlockingStub blockingStubFull = null; + private static final long now = System.currentTimeMillis(); + private static final long totalSupply = now; + private static final String name = "Asset008_" + Long.toString(now); + String description = "just-test"; + String url = "https://github.com/tronprotocol/wallet-cli/"; + Long delaySecond = 10L; + private static String accountId; + + private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") + .get(0); + private Long delayTransactionFee = Configuration.getByPath("testng.conf") + .getLong("defaultParameter.delayTransactionFee"); + private Long cancleDelayTransactionFee = Configuration.getByPath("testng.conf") + .getLong("defaultParameter.cancleDelayTransactionFee"); + ByteString assetId; + private byte[] contractAddress = null; + SmartContract smartContract; + + ECKey ecKey = new ECKey(Utils.getRandom()); + byte[] doSetIdAddress = ecKey.getAddress(); + String doSetIdKey = ByteArray.toHexString(ecKey.getPrivKeyBytes()); + + ECKey ecKey1 = new ECKey(Utils.getRandom()); + byte[] newAccountAddress = ecKey1.getAddress(); + String newAccountKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); + + @BeforeSuite + public void beforeSuite() { + Wallet wallet = new Wallet(); + Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); + } + + /** + * constructor. + */ + + @BeforeClass(enabled = false) + public void beforeClass() { + channelFull = ManagedChannelBuilder.forTarget(fullnode) + .usePlaintext(true) + .build(); + blockingStubFull = WalletGrpc.newBlockingStub(channelFull); + } + + @Test(enabled = false, description = "Delay set account id contract") + public void test1DelaySetAccountId() { + //get account + ecKey = new ECKey(Utils.getRandom()); + doSetIdAddress = ecKey.getAddress(); + doSetIdKey = ByteArray.toHexString(ecKey.getPrivKeyBytes()); + PublicMethed.printAddress(doSetIdKey); + + Assert.assertTrue(PublicMethed.sendcoin(doSetIdAddress, 10000000L, fromAddress, + testKey002, blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + final Long beforeSetAccountIdBalance = PublicMethed.queryAccount(doSetIdKey, + blockingStubFull).getBalance(); + accountId = "accountId_" + Long.toString(System.currentTimeMillis()); + byte[] accountIdBytes = ByteArray.fromString(accountId); + final String txid = PublicMethed.setAccountIdDelayGetTxid(accountIdBytes, + delaySecond,doSetIdAddress,doSetIdKey,blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + String getAccountId = new String(PublicMethed.queryAccount(doSetIdKey, + blockingStubFull).getAccountId().toByteArray(), Charset.forName("UTF-8")); + Assert.assertTrue(getAccountId.isEmpty()); + + Long balanceInDelay = PublicMethed.queryAccount(doSetIdKey,blockingStubFull) + .getBalance(); + Assert.assertTrue(beforeSetAccountIdBalance - balanceInDelay == delayTransactionFee); + PublicMethed.waitProduceNextBlock(blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + getAccountId = new String(PublicMethed.queryAccount(doSetIdKey,blockingStubFull) + .getAccountId().toByteArray(), Charset.forName("UTF-8")); + logger.info(accountId); + Assert.assertTrue(accountId.equalsIgnoreCase(getAccountId)); + Long afterCreateAccountBalance = PublicMethed.queryAccount(doSetIdKey,blockingStubFull) + .getBalance(); + Long netFee = PublicMethed.getTransactionInfoById(txid,blockingStubFull).get().getReceipt() + .getNetFee(); + Long fee = PublicMethed.getTransactionInfoById(txid,blockingStubFull).get().getFee(); + Assert.assertTrue(fee - netFee == delayTransactionFee); + Assert.assertTrue(beforeSetAccountIdBalance - afterCreateAccountBalance + == delayTransactionFee); + + } + + @Test(enabled = false, description = "Cancel delay set account id contract") + public void test2CancelDelayUpdateAccount() { + //get account + ecKey = new ECKey(Utils.getRandom()); + doSetIdAddress = ecKey.getAddress(); + doSetIdKey = ByteArray.toHexString(ecKey.getPrivKeyBytes()); + PublicMethed.printAddress(doSetIdKey); + + Assert.assertTrue(PublicMethed.sendcoin(doSetIdAddress, 10000000L, fromAddress, + testKey002, blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + + final Long beforeSetAccountIdBalance = PublicMethed.queryAccount(doSetIdKey, + blockingStubFull).getBalance(); + accountId = "accountId_" + Long.toString(System.currentTimeMillis()); + byte[] accountIdBytes = ByteArray.fromString(accountId); + final String txid = PublicMethed.setAccountIdDelayGetTxid(accountIdBytes, + delaySecond,doSetIdAddress,doSetIdKey,blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + Assert.assertFalse(PublicMethed.cancelDeferredTransactionById(txid,fromAddress,testKey002, + blockingStubFull)); + final String cancelTxid = PublicMethed.cancelDeferredTransactionByIdGetTxid(txid, + doSetIdAddress,doSetIdKey,blockingStubFull); + Assert.assertFalse(PublicMethed.cancelDeferredTransactionById(txid,doSetIdAddress, + doSetIdKey,blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + final Long afterUpdateBalance = PublicMethed.queryAccount(doSetIdKey,blockingStubFull) + .getBalance(); + final Long netFee = PublicMethed.getTransactionInfoById(cancelTxid,blockingStubFull).get() + .getReceipt().getNetFee(); + final Long fee = PublicMethed.getTransactionInfoById(cancelTxid,blockingStubFull).get() + .getFee(); + logger.info("net fee : " + PublicMethed.getTransactionInfoById(cancelTxid,blockingStubFull) + .get().getReceipt().getNetFee()); + logger.info("Fee : " + PublicMethed.getTransactionInfoById(cancelTxid,blockingStubFull) + .get().getFee()); + + Assert.assertTrue(fee - netFee == cancleDelayTransactionFee); + Assert.assertTrue(beforeSetAccountIdBalance - afterUpdateBalance + == cancleDelayTransactionFee + delayTransactionFee); + + } + + + /** + * constructor. + */ + + @AfterClass(enabled = false) + public void shutdown() throws InterruptedException { + if (channelFull != null) { + channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); + } + } +} + + diff --git a/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction010.java b/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction010.java new file mode 100644 index 00000000000..93bd0094b45 --- /dev/null +++ b/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction010.java @@ -0,0 +1,234 @@ +package stest.tron.wallet.dailybuild.delaytransaction; + +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import java.util.Optional; +import java.util.concurrent.TimeUnit; +import lombok.extern.slf4j.Slf4j; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeSuite; +import org.testng.annotations.Test; +import org.tron.api.WalletGrpc; +import org.tron.common.crypto.ECKey; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.Utils; +import org.tron.core.Wallet; +//import org.tron.protos.Protocol.DeferredTransaction; +import org.tron.protos.Protocol.Transaction; +import org.tron.protos.Protocol.TransactionInfo; +import stest.tron.wallet.common.client.Configuration; +import stest.tron.wallet.common.client.Parameter.CommonConstant; +import stest.tron.wallet.common.client.utils.Base58; +import stest.tron.wallet.common.client.utils.PublicMethed; +import stest.tron.wallet.common.client.utils.Sha256Hash; + +@Slf4j +public class DelayTransaction010 { + + private final String testKey002 = Configuration.getByPath("testng.conf") + .getString("foundationAccount.key1"); + private final String testKey003 = Configuration.getByPath("testng.conf") + .getString("foundationAccount.key2"); + private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); + + private ManagedChannel channelFull = null; + private WalletGrpc.WalletBlockingStub blockingStubFull = null; + + private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") + .get(1); + private Long delayTransactionFee = Configuration.getByPath("testng.conf") + .getLong("defaultParameter.delayTransactionFee"); + private Long cancleDelayTransactionFee = Configuration.getByPath("testng.conf") + .getLong("defaultParameter.cancleDelayTransactionFee"); + + public static final long ONE_DELAY_SECONDS = 60 * 60 * 24L; + //Optional deferredTransactionById = null; + + ECKey ecKey = new ECKey(Utils.getRandom()); + byte[] delayFeeAccountAddress = ecKey.getAddress(); + String delayFeeAccountKey = ByteArray.toHexString(ecKey.getPrivKeyBytes()); + + ECKey ecKey2 = new ECKey(Utils.getRandom()); + byte[] delayAccount2Address = ecKey2.getAddress(); + String delayAccount2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); + + @BeforeSuite + public void beforeSuite() { + Wallet wallet = new Wallet(); + Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); + } + + /** + * constructor. + */ + + @BeforeClass(enabled = false) + public void beforeClass() { + channelFull = ManagedChannelBuilder.forTarget(fullnode) + .usePlaintext(true) + .build(); + blockingStubFull = WalletGrpc.newBlockingStub(channelFull); + } + + @Test(enabled = false, description = "Delayed transaction cost 0.1TRX every day.") + public void test1TestDelayedTransactionFee() { + //get account + ecKey = new ECKey(Utils.getRandom()); + delayFeeAccountAddress = ecKey.getAddress(); + delayFeeAccountKey = ByteArray.toHexString(ecKey.getPrivKeyBytes()); + + ecKey2 = new ECKey(Utils.getRandom()); + delayAccount2Address = ecKey2.getAddress(); + delayAccount2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); + + + PublicMethed.printAddress(delayFeeAccountKey); + Assert.assertTrue(PublicMethed.sendcoin(delayFeeAccountAddress, 100000000L,fromAddress, + testKey002, blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + final String txidZeroDay = PublicMethed.sendcoinDelayedGetTxid(delayAccount2Address, 1L, + 0,delayFeeAccountAddress, delayFeeAccountKey, blockingStubFull); + PublicMethed.cancelDeferredTransactionByIdGetTxid(txidZeroDay, + delayFeeAccountAddress,delayFeeAccountKey,blockingStubFull); + final String txidOneDay = PublicMethed.sendcoinDelayedGetTxid(delayAccount2Address, 1L, + ONE_DELAY_SECONDS - 1,delayFeeAccountAddress, delayFeeAccountKey, blockingStubFull); + final String txidTwoDay = PublicMethed.sendcoinDelayedGetTxid(delayAccount2Address, 1L, + ONE_DELAY_SECONDS * 2 - 1,delayFeeAccountAddress, delayFeeAccountKey, blockingStubFull); + final String txidFiveDay = PublicMethed.sendcoinDelayedGetTxid(delayAccount2Address, 1L, + ONE_DELAY_SECONDS * 6 - 1,delayFeeAccountAddress, delayFeeAccountKey, blockingStubFull); + final String txidTenDay = PublicMethed.sendcoinDelayedGetTxid(delayAccount2Address, 1L, + ONE_DELAY_SECONDS * 9,delayFeeAccountAddress, delayFeeAccountKey, blockingStubFull); + final String txid45Day = PublicMethed.sendcoinDelayedGetTxid(delayAccount2Address, 1L, + ONE_DELAY_SECONDS * 45,delayFeeAccountAddress, delayFeeAccountKey, blockingStubFull); + final String txid28Day = PublicMethed.sendcoinDelayedGetTxid(delayAccount2Address, 1L, + ONE_DELAY_SECONDS * 28 - 1000,delayFeeAccountAddress, delayFeeAccountKey, blockingStubFull); + + PublicMethed.waitProduceNextBlock(blockingStubFull); + Assert.assertTrue(PublicMethed.getTransactionInfoById(txidZeroDay,blockingStubFull) + .get().getFee() == delayTransactionFee); + Assert.assertTrue(PublicMethed.getTransactionInfoById(txidOneDay,blockingStubFull) + .get().getFee() == delayTransactionFee); + Assert.assertTrue(PublicMethed.getTransactionInfoById(txidTwoDay,blockingStubFull) + .get().getFee() == delayTransactionFee * 2); + Assert.assertTrue(PublicMethed.getTransactionInfoById(txidFiveDay,blockingStubFull) + .get().getFee() == delayTransactionFee * 6); + Assert.assertTrue(PublicMethed.getTransactionInfoById(txidTenDay,blockingStubFull) + .get().getFee() == delayTransactionFee * 10); + Assert.assertTrue(PublicMethed.getTransactionInfoById(txid45Day,blockingStubFull) + .get().getFee() == delayTransactionFee * 46); + Assert.assertTrue(PublicMethed.getTransactionInfoById(txid28Day,blockingStubFull) + .get().getFee() == delayTransactionFee * 28); + + String cancelTxid = PublicMethed.cancelDeferredTransactionByIdGetTxid(txid28Day, + delayFeeAccountAddress,delayFeeAccountKey,blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + Assert.assertTrue(PublicMethed.getTransactionInfoById(cancelTxid,blockingStubFull) + .get().getFee() == cancleDelayTransactionFee); + } + + /** + * constructor. + * */ + @Test(enabled = false, description = "Delayed transaction finally fialed.") + public void test2DelaydTransactionFinallyFailed() { + Long sendAmount = 12345L; + Long beforeBalance = PublicMethed.queryAccount(delayFeeAccountAddress,blockingStubFull) + .getBalance(); + final String preTxid = PublicMethed.sendcoinDelayedGetTxid(delayAccount2Address, sendAmount, + 6L,delayFeeAccountAddress, delayFeeAccountKey, blockingStubFull); + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + //deferredTransactionById = PublicMethed.getDeferredTransactionById(preTxid,blockingStubFull); + //DeferredTransaction transaction = deferredTransactionById.get(); + //String finalTxid = ByteArray.toHexString(Sha256Hash.hash(transaction.getTransaction() + // .getRawData().toByteArray())); + + Assert.assertTrue(PublicMethed.sendcoin(fromAddress,PublicMethed.queryAccount( + delayFeeAccountAddress, blockingStubFull).getBalance(),delayFeeAccountAddress, + delayFeeAccountKey,blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + //Assert.assertTrue(PublicMethed.getTransactionById(finalTxid,blockingStubFull) + // .get().getRawData().getContractCount() == 0); + + Long afterBalance = PublicMethed.queryAccount(delayFeeAccountAddress,blockingStubFull) + .getBalance(); + Long afterSendCoinAccount2Balance = PublicMethed.queryAccount(delayAccount2Address, + blockingStubFull).getBalance(); + Long beforeSendCoinAccount2Balance = PublicMethed.queryAccount(delayAccount2Address, + blockingStubFull).getBalance(); + //Assert.assertTrue(beforeBalance - afterBalance == delayTransactionFee); + Assert.assertTrue(beforeSendCoinAccount2Balance == afterSendCoinAccount2Balance); + } + + /** + * constructor. + * */ + @Test(enabled = false, description = "Delayed transaction finally successfully even during " + + "delaying time the account has no money has no money.") + public void test3DelaydTransactionFinallySuccessfully() { + Assert.assertTrue(PublicMethed.sendcoin(delayFeeAccountAddress,10000000L,fromAddress, + testKey002,blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + Long sendAmount = 5432L; + Long beforeBalance = PublicMethed.queryAccount(delayFeeAccountAddress,blockingStubFull) + .getBalance(); + final String preTxid = PublicMethed.sendcoinDelayedGetTxid(delayAccount2Address, sendAmount, + 9L,delayFeeAccountAddress, delayFeeAccountKey, blockingStubFull); + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + //deferredTransactionById = PublicMethed.getDeferredTransactionById(preTxid,blockingStubFull); + //DeferredTransaction transaction = deferredTransactionById.get(); + //String finalTxid = ByteArray.toHexString(Sha256Hash.hash(transaction.getTransaction() + // .getRawData().toByteArray())); + Assert.assertTrue(PublicMethed.sendcoin(fromAddress,PublicMethed.queryAccount( + delayFeeAccountAddress, blockingStubFull).getBalance(),delayFeeAccountAddress, + delayFeeAccountKey,blockingStubFull)); + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + Assert.assertTrue(PublicMethed.sendcoin(delayFeeAccountAddress,10000000L,fromAddress, + testKey002,blockingStubFull)); + + PublicMethed.waitProduceNextBlock(blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + //Assert.assertTrue(PublicMethed.getTransactionById(finalTxid,blockingStubFull) + // .get().getRawData().getContractCount() == 1); + + Long afterBalance = PublicMethed.queryAccount(delayFeeAccountAddress,blockingStubFull) + .getBalance(); + Long afterSendCoinAccount2Balance = PublicMethed.queryAccount(delayAccount2Address, + blockingStubFull).getBalance(); + Long beforeSendCoinAccount2Balance = PublicMethed.queryAccount(delayAccount2Address, + blockingStubFull).getBalance(); + Assert.assertTrue(beforeSendCoinAccount2Balance + sendAmount == afterSendCoinAccount2Balance); + + } + + + /** + * constructor. + * */ + + @AfterClass(enabled = false) + public void shutdown() throws InterruptedException { + if (channelFull != null) { + channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); + } + } +} + + diff --git a/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction011.java b/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction011.java new file mode 100644 index 00000000000..2bcbefc9ece --- /dev/null +++ b/src/test/java/stest/tron/wallet/dailybuild/delaytransaction/DelayTransaction011.java @@ -0,0 +1,135 @@ +package stest.tron.wallet.dailybuild.delaytransaction; + +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import java.util.Optional; +import java.util.concurrent.TimeUnit; +import lombok.extern.slf4j.Slf4j; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeSuite; +import org.testng.annotations.Test; +import org.tron.api.WalletGrpc; +import org.tron.common.crypto.ECKey; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.Utils; +import org.tron.core.Wallet; +//import org.tron.protos.Protocol.DeferredTransaction; +import stest.tron.wallet.common.client.Configuration; +import stest.tron.wallet.common.client.Parameter.CommonConstant; +import stest.tron.wallet.common.client.utils.PublicMethed; +import stest.tron.wallet.common.client.utils.Sha256Hash; + +@Slf4j +public class DelayTransaction011 { + + private final String testKey002 = Configuration.getByPath("testng.conf") + .getString("foundationAccount.key1"); + private final String testKey003 = Configuration.getByPath("testng.conf") + .getString("foundationAccount.key2"); + private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); + + private ManagedChannel channelFull = null; + private WalletGrpc.WalletBlockingStub blockingStubFull = null; + + private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") + .get(1); + private Long delayTransactionFee = Configuration.getByPath("testng.conf") + .getLong("defaultParameter.delayTransactionFee"); + private Long cancleDelayTransactionFee = Configuration.getByPath("testng.conf") + .getLong("defaultParameter.cancleDelayTransactionFee"); + + public static final long ONE_DELAY_SECONDS = 60 * 60 * 24L; + //Optional deferredTransactionById = null; + + ECKey ecKey = new ECKey(Utils.getRandom()); + byte[] noBandwidthAddress = ecKey.getAddress(); + String noBandwidthKey = ByteArray.toHexString(ecKey.getPrivKeyBytes()); + + ECKey ecKey2 = new ECKey(Utils.getRandom()); + byte[] delayAccount2Address = ecKey2.getAddress(); + String delayAccount2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); + + @BeforeSuite + public void beforeSuite() { + Wallet wallet = new Wallet(); + Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); + } + + /** + * constructor. + */ + + @BeforeClass(enabled = false) + public void beforeClass() { + channelFull = ManagedChannelBuilder.forTarget(fullnode) + .usePlaintext(true) + .build(); + blockingStubFull = WalletGrpc.newBlockingStub(channelFull); + } + + @Test(enabled = false, description = "When Bandwidth not enough, create delay transaction.") + public void test1BandwidthInDelayTransaction() { + //get account + ecKey = new ECKey(Utils.getRandom()); + noBandwidthAddress = ecKey.getAddress(); + noBandwidthKey = ByteArray.toHexString(ecKey.getPrivKeyBytes()); + PublicMethed.printAddress(noBandwidthKey); + ecKey2 = new ECKey(Utils.getRandom()); + delayAccount2Address = ecKey2.getAddress(); + delayAccount2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); + PublicMethed.printAddress(delayAccount2Key); + + + Assert.assertTrue(PublicMethed.sendcoin(noBandwidthAddress, 10000000000L,fromAddress, + testKey002, blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + while (PublicMethed.queryAccount(noBandwidthAddress,blockingStubFull).getFreeNetUsage() + < 4700L) { + PublicMethed.sendcoin(delayAccount2Address,1L,noBandwidthAddress,noBandwidthKey, + blockingStubFull); + } + PublicMethed.sendcoin(delayAccount2Address,1L,noBandwidthAddress,noBandwidthKey, + blockingStubFull); + PublicMethed.sendcoin(delayAccount2Address,1L,noBandwidthAddress,noBandwidthKey, + blockingStubFull); + Assert.assertTrue(PublicMethed.sendcoin(fromAddress,PublicMethed.queryAccount( + noBandwidthAddress,blockingStubFull).getBalance() - 3000L,noBandwidthAddress, + noBandwidthKey,blockingStubFull)); + logger.info("balance is: " + PublicMethed.queryAccount(noBandwidthAddress, + blockingStubFull).getBalance()); + logger.info("Free net usage is " + PublicMethed.queryAccount(noBandwidthAddress, + blockingStubFull).getFreeNetUsage()); + + String updateAccountName = "account_" + Long.toString(System.currentTimeMillis()); + byte[] accountNameBytes = ByteArray.fromString(updateAccountName); + String txid = PublicMethed.updateAccountDelayGetTxid(noBandwidthAddress,accountNameBytes, + 10L,noBandwidthKey,blockingStubFull); + logger.info(txid); + Assert.assertTrue(PublicMethed.getTransactionById(txid,blockingStubFull) + .get().getRawData().getContractCount() == 0); + + Assert.assertTrue(PublicMethed.sendcoin(noBandwidthAddress, 103332L - 550L,fromAddress, + testKey002, blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + txid = PublicMethed.updateAccountDelayGetTxid(noBandwidthAddress,accountNameBytes, + 10L,noBandwidthKey,blockingStubFull); + + } + + + /** + * constructor. + * */ + + @AfterClass(enabled = false) + public void shutdown() throws InterruptedException { + if (channelFull != null) { + channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); + } + } +} + + diff --git a/src/test/java/stest/tron/wallet/dailybuild/exceptionfee/AssertException.java b/src/test/java/stest/tron/wallet/dailybuild/exceptionfee/AssertException.java index f623fcb8142..0483818e30e 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/exceptionfee/AssertException.java +++ b/src/test/java/stest/tron/wallet/dailybuild/exceptionfee/AssertException.java @@ -2,6 +2,7 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -94,11 +95,12 @@ public void test1DivideInt() { blockingStubFull)); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName = "divideInt"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_AssertException_testdivideInt"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_AssertException_testdivideInt"); + String filePath = "src/test/resources/soliditycode/assertExceptiontest1DivideInt.sol"; + String contractName = "divideIHaveArgsReturnStorage"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contractExcKey, @@ -131,7 +133,6 @@ public void test1DivideInt() { Long netUsed = infoById.get().getReceipt().getNetUsage(); Long energyUsed = infoById.get().getReceipt().getEnergyUsage(); Long netFee = infoById.get().getReceipt().getNetFee(); - logger.info("fee:" + fee); logger.info("netUsed:" + netUsed); logger.info("energyUsed:" + energyUsed); @@ -157,11 +158,13 @@ public void test1DivideInt() { @Test(enabled = true, description = "Trigger contract index out of bounds") public void test2FindArgsContractMinTest() { - String contractName = "findArgsContractTest"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_AssertException_testfindArgsContractMinTest"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_AssertException_testfindArgsContractMinTest"); + String filePath = + "src/test/resources/soliditycode/assertExceptiontest2FindArgsContractMinTest.sol"; + String contractName = "findArgsIContract"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contractExcKey, contractExcAddress, blockingStubFull); @@ -182,7 +185,7 @@ public void test2FindArgsContractMinTest() { String txid = ""; Integer triggerNum = -1; txid = PublicMethed.triggerContract(contractAddress, - "findArgsByIndexTest(uint256)", triggerNum.toString(), false, + "findArgsByIndex1(uint256)", triggerNum.toString(), false, 0, maxFeeLimit, contractExcAddress, contractExcKey, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull1); @@ -219,11 +222,12 @@ public void test2FindArgsContractMinTest() { @Test(enabled = true, description = "Trigger contract Bytes array index out of bounds") public void test3ByteMinContract() { + String filePath = "src/test/resources/soliditycode/assertExceptiontest3ByteMinContract.sol"; String contractName = "byteContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_AssertException_testbyteMinContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_AssertException_testbyteMinContract"); + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contractExcKey, contractExcAddress, blockingStubFull); @@ -281,11 +285,11 @@ public void test3ByteMinContract() { @Test(enabled = true, description = "Trigger contract convert too large value to enumerated type") public void test4Enum() { - String contractName = "enum"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_AssertException_testenum"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_AssertException_testenum"); + String filePath = "src/test/resources/soliditycode/assertExceptiontest4Enum.sol"; + String contractName = "enumContract"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contractExcKey, contractExcAddress, blockingStubFull); @@ -344,11 +348,12 @@ public void test4Enum() { @Test(enabled = true, description = "Trigger contract move a negative value to a binary") public void test5MoveRight() { - String contractName = "moveRight"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_AssertException_testmoveRight"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_AssertException_testmoveRight"); + String filePath = "src/test/resources/soliditycode/assertExceptiontest5MoveRight.sol"; + String contractName = "binaryRightContract"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contractExcKey, contractExcAddress, blockingStubFull); @@ -409,11 +414,13 @@ public void test5MoveRight() { @Test(enabled = true, description = "Trigger contract Call an uninitialized " + "internal function type variable") public void test6UninitializedContract() { - String contractName = "uninitializedContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_AssertException_testuninitializedContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_AssertException_testuninitializedContract"); + String filePath = + "src/test/resources/soliditycode/assertExceptiontest6UninitializedContract.sol"; + String contractName = "uni"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contractExcKey, contractExcAddress, blockingStubFull); @@ -471,11 +478,12 @@ public void test6UninitializedContract() { @Test(enabled = true, description = "Trigger contract assert exception") public void test7TestAssertContract() { + String filePath = "src/test/resources/soliditycode/assertExceptiontest7TestAssertContract.sol"; String contractName = "TestThrowsContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_AssertException_testTestAssertContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_AssertException_testTestAssertContract"); + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contractExcKey, contractExcAddress, blockingStubFull); diff --git a/src/test/java/stest/tron/wallet/dailybuild/grammar/ContractGrammar001.java b/src/test/java/stest/tron/wallet/dailybuild/grammar/ContractGrammar001.java index 84637abc1a5..5454a596020 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/grammar/ContractGrammar001.java +++ b/src/test/java/stest/tron/wallet/dailybuild/grammar/ContractGrammar001.java @@ -2,6 +2,7 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -46,6 +47,8 @@ public class ContractGrammar001 { .getStringList("fullnode.ip.list").get(1); private String fullnode1 = Configuration.getByPath("testng.conf") .getStringList("fullnode.ip.list").get(0); + private String compilerVersion = Configuration.getByPath("testng.conf") + .getString("defaultParameter.solidityCompilerVersion"); byte[] contractAddress = null; @@ -88,11 +91,12 @@ public void test1Grammar001() { .sendcoin(grammarAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, blockingStubFull)); PublicMethed.waitProduceNextBlock(blockingStubFull); + String filePath = "src/test/resources/soliditycode/contractGrammar001test1Grammar001.sol"; String contractName = "FunctionSelector"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractGrammar001_testGrammar001"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractGrammar001_testGrammar001"); + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, testKeyForGrammarAddress, grammarAddress, blockingStubFull); @@ -124,11 +128,12 @@ public void test1Grammar001() { @Test(enabled = true, description = "Ordinary library contract") public void test2Grammar002() { - String contractName = "SetContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractGrammar001_testGrammar002"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractGrammar001_testGrammar002"); + String filePath = "src/test/resources/soliditycode/contractGrammar001test2Grammar002.sol"; + String contractName = "Set"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, testKeyForGrammarAddress, grammarAddress, blockingStubFull); @@ -136,16 +141,17 @@ public void test2Grammar002() { String txid = ""; String num = "1"; byte[] contractAddress1 = null; - String contractName1 = "CContract"; - String code1 = Configuration.getByPath("testng.conf") - .getString("code.code1_ContractGrammar001_testGrammar002"); - String abi1 = Configuration.getByPath("testng.conf") - .getString("abi.abi1_ContractGrammar001_testGrammar002"); - String libraryAddress = - "browser/TvmTest_p1_Grammar_002.sol:S:" + Base58.encode58Check(contractAddress); - contractAddress1 = PublicMethed.deployContract(contractName1, abi1, code1, "", maxFeeLimit, - 0L, 100, libraryAddress, testKeyForGrammarAddress, - grammarAddress, blockingStubFull); + String filePath1 = "src/test/resources/soliditycode/contractGrammar001test2Grammar002.sol"; + String contractName1 = "C"; + HashMap retMap1 = PublicMethed.getBycodeAbiForLibrary(filePath1, contractName1); + String code1 = retMap1.get("byteCode").toString(); + String abi1 = retMap1.get("abI").toString(); + String library = retMap1.get("library").toString(); + String libraryAddress = library + Base58.encode58Check(contractAddress); + contractAddress1 = PublicMethed + .deployContractForLibrary(contractName1, abi1, code1, "", maxFeeLimit, + 0L, 100, libraryAddress, testKeyForGrammarAddress, + grammarAddress, compilerVersion, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); txid = PublicMethed.triggerContract(contractAddress1, "register(uint256)", num, false, @@ -160,11 +166,11 @@ public void test2Grammar002() { @Test(enabled = true, description = "Library contract") public void test3Grammar003() { - String contractName = "SetContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractGrammar001_testGrammar003"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractGrammar001_testGrammar003"); + String filePath = "src/test/resources/soliditycode/contractGrammar001test3Grammar003.sol"; + String contractName = "Set"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, testKeyForGrammarAddress, grammarAddress, blockingStubFull); @@ -172,16 +178,17 @@ public void test3Grammar003() { String txid = ""; String num = "1"; byte[] contractAddress1 = null; - String contractName1 = "CContract"; - String code1 = Configuration.getByPath("testng.conf") - .getString("code.code1_ContractGrammar001_testGrammar003"); - String abi1 = Configuration.getByPath("testng.conf") - .getString("abi.abi1_ContractGrammar001_testGrammar003"); - String libraryAddress = - "browser/TvmTest_p1_Grammar_003.sol:S:" + Base58.encode58Check(contractAddress); - contractAddress1 = PublicMethed.deployContract(contractName1, abi1, code1, "", maxFeeLimit, - 0L, 100, libraryAddress, testKeyForGrammarAddress, - grammarAddress, blockingStubFull); + String contractName1 = "C"; + HashMap retMap1 = PublicMethed.getBycodeAbiForLibrary(filePath, contractName1); + String code1 = retMap1.get("byteCode").toString(); + String abi1 = retMap1.get("abI").toString(); + String library = retMap1.get("library").toString(); + String libraryAddress = library + + Base58.encode58Check(contractAddress); + contractAddress1 = PublicMethed + .deployContractForLibrary(contractName1, abi1, code1, "", maxFeeLimit, + 0L, 100, libraryAddress, testKeyForGrammarAddress, + grammarAddress, compilerVersion, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); txid = PublicMethed.triggerContract(contractAddress1, "register(uint256)", num, false, @@ -197,27 +204,37 @@ public void test3Grammar003() { @Test(enabled = true, description = "Extended type") public void test4Grammar004() { - String contractName = "searchContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractGrammar001_testGrammar004"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractGrammar001_testGrammar004"); + ecKey1 = new ECKey(Utils.getRandom()); + grammarAddress = ecKey1.getAddress(); + testKeyForGrammarAddress = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); + PublicMethed.waitProduceNextBlock(blockingStubFull); + Assert.assertTrue(PublicMethed + .sendcoin(grammarAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, + blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + String filePath = "src/test/resources/soliditycode/contractGrammar001test4Grammar004.sol"; + String contractName = "Search"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, testKeyForGrammarAddress, grammarAddress, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); byte[] contractAddress1 = null; - String contractName1 = "cContract"; - String code1 = Configuration.getByPath("testng.conf") - .getString("code.code1_ContractGrammar001_testGrammar004"); - String abi1 = Configuration.getByPath("testng.conf") - .getString("abi.abi1_ContractGrammar001_testGrammar004"); + String contractName1 = "C"; + HashMap retMap1 = PublicMethed.getBycodeAbiForLibrary(filePath, contractName1); + String code1 = retMap1.get("byteCode").toString(); + String abi1 = retMap1.get("abI").toString(); + String library = retMap1.get("library").toString(); String libraryAddress = null; - libraryAddress = - "browser/TvmTest_p1_Grammar_004.sol:S:" + Base58.encode58Check(contractAddress); - contractAddress1 = PublicMethed.deployContract(contractName1, abi1, code1, "", maxFeeLimit, - 0L, 100, libraryAddress, testKeyForGrammarAddress, - grammarAddress, blockingStubFull); + libraryAddress = library + + Base58.encode58Check(contractAddress); + contractAddress1 = PublicMethed + .deployContractForLibrary(contractName1, abi1, code1, "", maxFeeLimit, + 0L, 100, libraryAddress, testKeyForGrammarAddress, + grammarAddress, compilerVersion, blockingStubFull); String txid = ""; String num = "1"; PublicMethed.waitProduceNextBlock(blockingStubFull); @@ -260,11 +277,13 @@ public void test4Grammar004() { @Test(enabled = true, description = "Solidity assembly") public void test5Grammar006() { - String contractName = "infofeedContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractGrammar001_testGrammar006"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractGrammar001_testGrammar006"); + String filePath = "src/test/resources/soliditycode/contractGrammar001test5Grammar006.sol"; + String contractName = "InfoFeed"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, testKeyForGrammarAddress, grammarAddress, blockingStubFull); diff --git a/src/test/java/stest/tron/wallet/dailybuild/grammar/ContractGrammar002.java b/src/test/java/stest/tron/wallet/dailybuild/grammar/ContractGrammar002.java index 7e532d390de..a71da52602d 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/grammar/ContractGrammar002.java +++ b/src/test/java/stest/tron/wallet/dailybuild/grammar/ContractGrammar002.java @@ -2,6 +2,7 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -89,22 +90,22 @@ public void test1Grammar007() { .sendcoin(grammarAddress2, 100000000000L, testNetAccountAddress, testNetAccountKey, blockingStubFull)); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName = "dougContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractGrammar002_testGrammar007"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractGrammar002_testGrammar007"); + String filePath = "src/test/resources/soliditycode/contractGrammar002test1Grammar007_1.sol"; + String contractName = "Doug"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, testKeyForGrammarAddress2, grammarAddress2, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); String initParmes = ByteArray.toHexString(contractAddress); - String contractName1 = "mainContract"; - String code1 = Configuration.getByPath("testng.conf") - .getString("code.code1_ContractGrammar002_testGrammar007") + "0000000000000000000000" + String filePath1 = "src/test/resources/soliditycode/contractGrammar002test1Grammar007_2.sol"; + String contractName1 = "main"; + HashMap retMap1 = PublicMethed.getBycodeAbi(filePath1, contractName1); + String code1 = retMap1.get("byteCode").toString() + "0000000000000000000000" + initParmes; - String abi1 = Configuration.getByPath("testng.conf") - .getString("abi.abi1_ContractGrammar002_testGrammar007"); + String abi1 = retMap1.get("abI").toString(); byte[] contractAddress1 = PublicMethed .deployContract(contractName1, abi1, code1, "", maxFeeLimit, 0L, 100, null, testKeyForGrammarAddress2, @@ -124,7 +125,7 @@ public void test1Grammar007() { Assert.assertTrue(infoById1.get().getResultValue() == 0); String number1 = "687777"; - String txid2 = PublicMethed.triggerContract(contractAddress, + String txid2 = PublicMethed.triggerContract(contractAddress1, "uintOfName(bytes32)", number1, false, 0, maxFeeLimit, grammarAddress2, testKeyForGrammarAddress2, blockingStubFull); // PublicMethed.waitProduceNextBlock(blockingStubFull); @@ -137,11 +138,12 @@ public void test1Grammar007() { @Test(enabled = true, description = "Abstract function") public void test2Grammar008() { - String contractName = "catContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractGrammar002_testGrammar008"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractGrammar002_testGrammar008"); + String filePath = "src/test/resources/soliditycode/contractGrammar002test2Grammar008.sol"; + String contractName = "Cat"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, testKeyForGrammarAddress2, grammarAddress2, blockingStubFull); @@ -170,19 +172,28 @@ public void test2Grammar008() { @Test(enabled = true, description = "Gas, value test") public void test3Grammar010() { + String filePath = "src/test/resources/soliditycode/contractGrammar002test3Grammar010.sol"; + String contractName = "Consumer"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); - String contractName = "catContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractGrammar002_testGrammar010"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractGrammar002_testGrammar010"); contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 20L, 100, null, testKeyForGrammarAddress2, + 2000L, 100, null, testKeyForGrammarAddress2, grammarAddress2, blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + String contractName1 = "InfoFeed"; + HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); + String code1 = retMap1.get("byteCode").toString(); + String abi1 = retMap1.get("abI").toString(); + byte[] contractAddress1 = PublicMethed + .deployContract(contractName1, abi1, code1, "", maxFeeLimit, + 0, 100, null, testKeyForGrammarAddress2, + grammarAddress2, blockingStubFull); String txid = ""; - String initParmes = "\"" + Base58.encode58Check(grammarAddress2) + "\""; + String initParmes = "\"" + Base58.encode58Check(contractAddress1) + "\""; txid = PublicMethed.triggerContract(contractAddress, "setFeed(address)", initParmes, false, 0, maxFeeLimit, grammarAddress2, testKeyForGrammarAddress2, blockingStubFull); @@ -200,11 +211,11 @@ public void test3Grammar010() { @Test(enabled = true, description = "Call a named function") public void test4Grammar011() { - String contractName = "cContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractGrammar002_testGrammar011"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractGrammar002_testGrammar011"); + String filePath = "src/test/resources/soliditycode/contractGrammar002test4Grammar011.sol"; + String contractName = "C"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); byte[] contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, testKeyForGrammarAddress2, grammarAddress2, blockingStubFull); @@ -234,11 +245,12 @@ public void test4Grammar011() { @Test(enabled = true, description = "Call a native function") public void test5Grammar012() { - String contractName = "rtestContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractGrammar002_testGrammar012"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractGrammar002_testGrammar012"); + String filePath = "src/test/resources/soliditycode/contractGrammar002test4Grammar012.sol"; + String contractName = "rTest"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + byte[] contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, testKeyForGrammarAddress2, grammarAddress2, blockingStubFull); @@ -256,11 +268,12 @@ public void test5Grammar012() { @Test(enabled = true, description = "Call a Destructor function") public void test6Grammar013() { - String contractName = "executefallbackContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractGrammar002_testGrammar013"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractGrammar002_testGrammar013"); + String filePath = "src/test/resources/soliditycode/contractGrammar002test6Grammar013.sol"; + String contractName = "Counter"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + byte[] contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, testKeyForGrammarAddress2, grammarAddress2, blockingStubFull); diff --git a/src/test/java/stest/tron/wallet/dailybuild/grammar/ContractGrammar003.java b/src/test/java/stest/tron/wallet/dailybuild/grammar/ContractGrammar003.java index f2800556fab..cf54b27ce81 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/grammar/ContractGrammar003.java +++ b/src/test/java/stest/tron/wallet/dailybuild/grammar/ContractGrammar003.java @@ -2,6 +2,7 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -90,20 +91,20 @@ public void test1Grammar014() { .sendcoin(grammarAddress3, 100000000000L, testNetAccountAddress, testNetAccountKey, blockingStubFull)); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName = "aContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractGrammar003_testGrammar014"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractGrammar003_testGrammar014"); + String filePath = "src/test/resources/soliditycode/contractGrammar003test1Grammar014.sol"; + String contractName = "A"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + byte[] contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, testKeyForGrammarAddress3, grammarAddress3, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName1 = "bContract"; - String code1 = Configuration.getByPath("testng.conf") - .getString("code.code1_ContractGrammar003_testGrammar014"); - String abi1 = Configuration.getByPath("testng.conf") - .getString("abi.abi1_ContractGrammar003_testGrammar014"); + String contractName1 = "B"; + HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); + String code1 = retMap1.get("byteCode").toString(); + String abi1 = retMap1.get("abI").toString(); byte[] contractAddress1 = PublicMethed .deployContract(contractName1, abi1, code1, "", maxFeeLimit, 0L, 100, null, testKeyForGrammarAddress3, @@ -264,12 +265,11 @@ public void test1Grammar014() { @Test(enabled = true, description = "Fallback function ") public void test2Grammar015() { - - String contractName = "executefallbackContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractGrammar003_testGrammar015"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractGrammar003_testGrammar015"); + String filePath = "src/test/resources/soliditycode/contractGrammar003test2Grammar015.sol"; + String contractName = "ExecuteFallback"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); byte[] contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, testKeyForGrammarAddress3, grammarAddress3, blockingStubFull); @@ -304,12 +304,11 @@ public void test2Grammar015() { @Test(enabled = true, description = "Permission control ") public void test3Grammar016() { - - String contractName = "dContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractGrammar003_testGrammar016"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractGrammar003_testGrammar016"); + String filePath = "src/test/resources/soliditycode/contractGrammar003test3Grammar016.sol"; + String contractName = "D"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); byte[] contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, testKeyForGrammarAddress3, grammarAddress3, blockingStubFull); @@ -322,12 +321,11 @@ public void test3Grammar016() { infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); Assert.assertTrue(infoById.get().getResultValue() == 0); + String contractName1 = "E"; + HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); + String code1 = retMap1.get("byteCode").toString(); + String abi1 = retMap1.get("abI").toString(); - String contractName1 = "eContract"; - String code1 = Configuration.getByPath("testng.conf") - .getString("code.code1_ContractGrammar003_testGrammar016"); - String abi1 = Configuration.getByPath("testng.conf") - .getString("abi.abi1_ContractGrammar003_testGrammar016"); byte[] contractAddress1 = PublicMethed .deployContract(contractName1, abi1, code1, "", maxFeeLimit, 0L, 100, null, testKeyForGrammarAddress3, @@ -368,12 +366,11 @@ public void test3Grammar016() { @Test(enabled = true, description = "Structure") public void test4Grammar017() { - - String contractName = "crowdfundingContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractGrammar003_testGrammar017"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractGrammar003_testGrammar017"); + String filePath = "src/test/resources/soliditycode/contractGrammar003test4Grammar017.sol"; + String contractName = "CrowdFunding"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); byte[] contractAddress1 = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, testKeyForGrammarAddress3, grammarAddress3, blockingStubFull); @@ -414,12 +411,11 @@ public void test4Grammar017() { @Test(enabled = true, description = "Built-in function") public void test5Grammar018() { - - String contractName = "grammar18Contract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractGrammar003_testGrammar018"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractGrammar003_testGrammar018"); + String filePath = "src/test/resources/soliditycode/contractGrammar003test5Grammar018.sol"; + String contractName = "Grammar18"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); byte[] contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, testKeyForGrammarAddress3, grammarAddress3, blockingStubFull); @@ -479,11 +475,12 @@ public void test5Grammar018() { @Test(enabled = true, description = "Time unit") public void test6Grammar019() { - String contractName = "timetestContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractGrammar003_testGrammar019"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractGrammar003_testGrammar019"); + String filePath = "src/test/resources/soliditycode/contractGrammar003test6Grammar019.sol"; + String contractName = "timetest"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + byte[] contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, testKeyForGrammarAddress3, grammarAddress3, blockingStubFull); @@ -501,18 +498,18 @@ public void test6Grammar019() { @Test(enabled = true, description = "Trx and sun unit conversion.") public void test7Grammar020() { + String filePath = "src/test/resources/soliditycode/contractGrammar003test7Grammar020.sol"; + String contractName = "trxtest"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); - String contractName = "TrxContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractGrammar003_testGrammar020"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractGrammar003_testGrammar020"); byte[] contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, testKeyForGrammarAddress3, grammarAddress3, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); String txid = PublicMethed.triggerContract(contractAddress, - "timetest()", "#", false, + "test()", "#", false, 0, maxFeeLimit, grammarAddress3, testKeyForGrammarAddress3, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); Optional infoById = null; diff --git a/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestAccount004.java b/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestAccount004.java new file mode 100644 index 00000000000..3cf78125602 --- /dev/null +++ b/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestAccount004.java @@ -0,0 +1,100 @@ +package stest.tron.wallet.dailybuild.http; + +import com.alibaba.fastjson.JSONObject; +import lombok.extern.slf4j.Slf4j; +import org.apache.http.HttpResponse; +import org.junit.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.Test; +import org.tron.common.crypto.ECKey; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.Utils; +import stest.tron.wallet.common.client.Configuration; +import stest.tron.wallet.common.client.utils.HttpMethed; +import stest.tron.wallet.common.client.utils.PublicMethed; + +@Slf4j +public class HttpTestAccount004 { + + private final String testKey002 = Configuration.getByPath("testng.conf") + .getString("foundationAccount.key1"); + private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); + private JSONObject responseContent; + private HttpResponse response; + private String httpnode = Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list") + .get(0); + private String httpSoliditynode = Configuration.getByPath("testng.conf") + .getStringList("httpnode.ip.list").get(2); + + ECKey ecKey1 = new ECKey(Utils.getRandom()); + byte[] setAccountIdAddress = ecKey1.getAddress(); + String setAccountIdKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); + Long amount = 10000000L; + String accountId; + + + /** + * constructor. + */ + @Test(enabled = true, description = "Set account by http") + public void test1setAccountId() { + response = HttpMethed.sendCoin(httpnode, fromAddress, setAccountIdAddress, amount, testKey002); + Assert.assertTrue(HttpMethed.verificationResult(response)); + HttpMethed.waitToProduceOneBlock(httpnode); + + + response = HttpMethed.setAccountId(httpnode,setAccountIdAddress, + System.currentTimeMillis() + "id",false,setAccountIdKey); + Assert.assertFalse(HttpMethed.verificationResult(response)); + + + //Set account id. + accountId = System.currentTimeMillis() + "id"; + response = HttpMethed.setAccountId(httpnode,setAccountIdAddress, + accountId,true,setAccountIdKey); + Assert.assertTrue(HttpMethed.verificationResult(response)); + } + + /** + * constructor. + */ + @Test(enabled = true, description = "Get account by id via http") + public void test2getAccountId() { + response = HttpMethed.getAccountById(httpnode,accountId,true); + responseContent = HttpMethed.parseResponseContent(response); + HttpMethed.printJsonContent(responseContent); + Assert.assertEquals(responseContent.get("account_id"), accountId); + Assert.assertTrue(responseContent.size() >= 10); + + response = HttpMethed.getAccountById(httpnode,accountId,false); + responseContent = HttpMethed.parseResponseContent(response); + HttpMethed.printJsonContent(responseContent); + Assert.assertTrue(responseContent.size() <= 1); + + + } + + /** + * constructor. + */ + @Test(enabled = true, description = "Get account by id via http") + public void test3getAccountIdFromSolidity() { + HttpMethed.waitToProduceOneBlockFromSolidity(httpnode,httpSoliditynode); + response = HttpMethed.getAccountByIdFromSolidity(httpSoliditynode,accountId,true); + responseContent = HttpMethed.parseResponseContent(response); + HttpMethed.printJsonContent(responseContent); + Assert.assertEquals(responseContent.get("account_id"), accountId); + Assert.assertTrue(responseContent.size() >= 10); + } + + + + /** + * constructor. + */ + + @AfterClass + public void shutdown() throws InterruptedException { + HttpMethed.disConnect(); + } +} diff --git a/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestAsset001.java b/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestAsset001.java index 8d1b48cdd10..f79c626faf4 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestAsset001.java +++ b/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestAsset001.java @@ -129,6 +129,7 @@ public void test05GetAssetIssueByNameFromSolidity() { */ @Test(enabled = true, description = "TransferAsset by http") public void test06TransferAsset() { + logger.info("Transfer asset."); response = HttpMethed.transferAsset(httpnode, assetAddress, participateAddress, assetIssueId, 100L, assetKey); Assert.assertTrue(HttpMethed.verificationResult(response)); @@ -137,6 +138,8 @@ public void test06TransferAsset() { responseContent = HttpMethed.parseResponseContent(response); HttpMethed.printJsonContent(responseContent); Assert.assertTrue(!responseContent.getString("assetV2").isEmpty()); + //logger.info(responseContent.get("assetV2").toString()); + } /** diff --git a/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestBlock001.java b/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestBlock001.java index 00fc973942f..c7939f53c8c 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestBlock001.java +++ b/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestBlock001.java @@ -137,11 +137,25 @@ public void get07BlockById() { Assert.assertEquals(blockId, responseContent.get("blockID").toString()); } + /** + * constructor. + */ + @Test(enabled = true, description = "GetBlockById by http") + public void get08BlockByIdFromSolidity() { + response = HttpMethed.getBlockByIdFromSolidity(httpSoliditynode, blockId); + Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); + responseContent = HttpMethed.parseResponseContent(response); + HttpMethed.printJsonContent(responseContent); + Assert.assertEquals(blockId, responseContent.get("blockID").toString()); + } + + + /** * constructor. */ @Test(enabled = true, description = "List nodes by http") - public void get08ListNodes() { + public void get09ListNodes() { response = HttpMethed.listNodes(httpnode); responseContent = HttpMethed.parseResponseContent(response); HttpMethed.printJsonContent(responseContent); @@ -152,7 +166,7 @@ public void get08ListNodes() { * constructor. */ @Test(enabled = true, description = "get next maintenance time by http") - public void get09NextMaintaenanceTime() { + public void get10NextMaintaenanceTime() { response = HttpMethed.getNextmaintenanceTime(httpnode); responseContent = HttpMethed.parseResponseContent(response); HttpMethed.printJsonContent(responseContent); @@ -165,7 +179,7 @@ public void get09NextMaintaenanceTime() { * constructor. */ @Test(enabled = true, description = "get chain parameter by http") - public void get10ChainParameter() { + public void get11ChainParameter() { response = HttpMethed.getChainParameter(httpnode); responseContent = HttpMethed.parseResponseContent(response); HttpMethed.printJsonContent(responseContent); @@ -185,7 +199,7 @@ public void get10ChainParameter() { * constructor. */ @Test(enabled = true, description = "get Node Info by http") - public void get11NodeInfo() { + public void get12NodeInfo() { response = HttpMethed.getNodeInfo(httpnode); responseContent = HttpMethed.parseResponseContent(response); HttpMethed.printJsonContent(responseContent); @@ -197,7 +211,7 @@ public void get11NodeInfo() { * constructor. */ @Test(enabled = true, description = "Get transaction count by blocknum from solidity by http") - public void get12TransactionCountByBlocknumFromSolidity() { + public void get13TransactionCountByBlocknumFromSolidity() { response = HttpMethed.getTransactionCountByBlocknumFromSolidity(httpSoliditynode, currentBlockNum); Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); @@ -207,6 +221,38 @@ public void get12TransactionCountByBlocknumFromSolidity() { Assert.assertTrue(Integer.parseInt(responseContent.get("count").toString()) >= 0); } + /** + * constructor. + */ + @Test(enabled = true, description = "GetBlockByLimitNext by http") + public void get14BlockByLimitNextFromSolidity() { + response = HttpMethed.getBlockByLimitNextFromSolidity(httpSoliditynode, + currentBlockNum - 10, currentBlockNum); + Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); + responseContent = HttpMethed.parseResponseContent(response); + HttpMethed.printJsonContent(responseContent); + logger.info(responseContent.get("block").toString()); + JSONArray jsonArray = JSONArray.parseArray(responseContent.get("block").toString()); + Assert.assertEquals(jsonArray.size(), 10); + } + + /** + * constructor. + */ + @Test(enabled = true, description = "GetBlockByLastNum by http") + public void get15BlockByLastNumFromSolidity() { + response = HttpMethed.getBlockByLastNumFromSolidity(httpSoliditynode, 8); + Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); + responseContent = HttpMethed.parseResponseContent(response); + HttpMethed.printJsonContent(responseContent); + logger.info(responseContent.get("block").toString()); + JSONArray jsonArray = JSONArray.parseArray(responseContent.get("block").toString()); + Assert.assertEquals(jsonArray.size(), 8); + } + + + + /** * constructor. */ diff --git a/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestConstantContract001.java b/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestConstantContract001.java new file mode 100644 index 00000000000..2ecfefe4e9d --- /dev/null +++ b/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestConstantContract001.java @@ -0,0 +1,120 @@ +package stest.tron.wallet.dailybuild.http; + +import com.alibaba.fastjson.JSONObject; +import java.util.HashMap; +import lombok.extern.slf4j.Slf4j; +import org.apache.http.HttpResponse; +import org.junit.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.Test; +import org.tron.common.crypto.ECKey; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.Utils; +import stest.tron.wallet.common.client.Configuration; +import stest.tron.wallet.common.client.utils.HttpMethed; +import stest.tron.wallet.common.client.utils.PublicMethed; + +@Slf4j +public class HttpTestConstantContract001 { + + private final String testKey002 = Configuration.getByPath("testng.conf") + .getString("foundationAccount.key1"); + private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); + private JSONObject responseContent; + private HttpResponse response; + private String httpnode = Configuration.getByPath("testng.conf").getStringList("httpnode.ip.list") + .get(0); + + ECKey ecKey2 = new ECKey(Utils.getRandom()); + byte[] assetOwnerAddress = ecKey2.getAddress(); + String assetOwnerKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); + String contractAddress; + + Long amount = 2048000000L; + + private static String contractName; + + + /** + * constructor. + */ + @Test(enabled = true, description = "Deploy constant contract by http") + public void test1DeployConstantContract() { + PublicMethed.printAddress(assetOwnerKey); + HttpMethed.waitToProduceOneBlock(httpnode); + response = HttpMethed.sendCoin(httpnode, fromAddress, assetOwnerAddress, amount, testKey002); + Assert.assertTrue(HttpMethed.verificationResult(response)); + HttpMethed.waitToProduceOneBlock(httpnode); + String filePath = "src/test/resources/soliditycode/constantContract001.sol"; + contractName = "testConstantContract"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + String txid = HttpMethed.deployContractGetTxid(httpnode, contractName, abi, code, 1000000L, + 1000000000L, 100, 11111111111111L, + 0L, 0, 0L, assetOwnerAddress, assetOwnerKey); + + HttpMethed.waitToProduceOneBlock(httpnode); + logger.info(txid); + response = HttpMethed.getTransactionById(httpnode, txid); + responseContent = HttpMethed.parseResponseContent(response); + HttpMethed.printJsonContent(responseContent); + Assert.assertTrue(!responseContent.getString("contract_address").isEmpty()); + contractAddress = responseContent.getString("contract_address"); + + response = HttpMethed.getTransactionInfoById(httpnode, txid); + responseContent = HttpMethed.parseResponseContent(response); + String receiptString = responseContent.getString("receipt"); + Assert + .assertEquals(HttpMethed.parseStringContent(receiptString).getString("result"), "SUCCESS"); + } + + /** + * constructor. + */ + @Test(enabled = true, description = "Get constant contract by http") + public void test2GetConstantContract() { + response = HttpMethed.getContract(httpnode, contractAddress); + responseContent = HttpMethed.parseResponseContent(response); + HttpMethed.printJsonContent(responseContent); + Assert.assertEquals(responseContent.getString("consume_user_resource_percent"), "100"); + Assert.assertEquals(responseContent.getString("contract_address"), contractAddress); + Assert.assertEquals(responseContent.getString("origin_address"), + ByteArray.toHexString(assetOwnerAddress)); + Assert.assertEquals(responseContent.getString("origin_energy_limit"), "11111111111111"); + Assert.assertEquals(responseContent.getString("name"), contractName); + } + + /** + * constructor. + */ + @Test(enabled = true, description = "Trigger constant contract without parameterString by http") + public void test3TriggerConstantContract() { + String param1 = "000000000000000000000000000000000000000000000000000000000000000" + + Integer.toHexString(3); + String param2 = "00000000000000000000000000000000000000000000000000000000000000" + + Integer.toHexString(30); + logger.info(param1); + logger.info(param2); + String param = param1 + param2; + logger.info(ByteArray.toHexString(assetOwnerAddress)); + response = HttpMethed.triggerConstantContract(httpnode, assetOwnerAddress, contractAddress, + "testPure(uint256,uint256)",param, 1000000000L, assetOwnerKey); + HttpMethed.waitToProduceOneBlock(httpnode); + responseContent = HttpMethed.parseResponseContent(response); + HttpMethed.printJsonContent(responseContent); + Assert.assertTrue(!responseContent.getString("transaction").isEmpty()); + JSONObject transactionObject = HttpMethed.parseStringContent( + responseContent.getString("transaction")); + Assert.assertTrue(!transactionObject.getString("raw_data").isEmpty()); + Assert.assertTrue(!transactionObject.getString("raw_data_hex").isEmpty()); + } + + /** + * constructor. + */ + @AfterClass + public void shutdown() throws InterruptedException { + HttpMethed.disConnect(); + } +} diff --git a/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestMutiSign001.java b/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestMutiSign001.java index 757ddb5d4aa..8247ae934f2 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestMutiSign001.java +++ b/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestMutiSign001.java @@ -31,8 +31,11 @@ public class HttpTestMutiSign001 { String ownerKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); Long amount = 1000000000L; JsonArray keys = new JsonArray(); + JsonArray activeKeys = new JsonArray(); JsonObject manager1Wight = new JsonObject(); JsonObject manager2Wight = new JsonObject(); + JsonObject manager3Wight = new JsonObject(); + JsonObject manager4Wight = new JsonObject(); JsonObject ownerObject = new JsonObject(); JsonObject witnessObject = new JsonObject(); JsonObject activeObject = new JsonObject(); @@ -45,6 +48,14 @@ public class HttpTestMutiSign001 { .getString("foundationAccount.key2"); private final byte[] manager2Address = PublicMethed.getFinalAddress(manager2Key); + private final String manager3Key = Configuration.getByPath("testng.conf") + .getString("witness.key1"); + private final byte[] manager3Address = PublicMethed.getFinalAddress(manager3Key); + + private final String manager4Key = Configuration.getByPath("testng.conf") + .getString("witness.key2"); + private final byte[] manager4Address = PublicMethed.getFinalAddress(manager4Key); + /** * constructor. */ @@ -71,12 +82,27 @@ public void test1AccountPermissionUpDate() { ownerObject.addProperty("threshold", 2); ownerObject.add("keys", keys); + + manager3Wight.addProperty("address", ByteArray.toHexString(manager3Address)); + manager3Wight.addProperty("weight", 1); + + logger.info(manager3Wight.toString()); + manager4Wight.addProperty("address", ByteArray.toHexString(manager4Address)); + manager4Wight.addProperty("weight", 1); + + logger.info(manager4Wight.toString()); + + activeKeys.add(manager3Wight); + activeKeys.add(manager4Wight); + + + activeObject.addProperty("type", 2); activeObject.addProperty("permission_name", "active0"); activeObject.addProperty("threshold", 2); activeObject.addProperty("operations", "7fff1fc0037e0000000000000000000000000000000000000000000000000000"); - activeObject.add("keys", keys); + activeObject.add("keys", activeKeys); response = HttpMethed.accountPermissionUpdate(httpnode, ownerAddress, ownerObject, witnessObject, activeObject, ownerKey); @@ -86,7 +112,7 @@ public void test1AccountPermissionUpDate() { /** * constructor. */ - @Test(enabled = true, description = "Add transaction sign by http") + @Test(enabled = true, description = "Add transaction sign by http with permission id") public void test2AddTransactionSign() { HttpMethed.waitToProduceOneBlock(httpnode); @@ -94,9 +120,29 @@ public void test2AddTransactionSign() { permissionKeyString[0] = manager1Key; permissionKeyString[1] = manager2Key; - response = HttpMethed.sendCoin(httpnode, ownerAddress, fromAddress, 10L, permissionKeyString); + String[] permissionKeyActive = new String[2]; + permissionKeyActive[0] = manager3Key; + permissionKeyActive[1] = manager4Key; + + response = HttpMethed.sendCoin(httpnode, ownerAddress, fromAddress, 10L, 0,permissionKeyString); + Assert.assertTrue(HttpMethed.verificationResult(response)); + + response = HttpMethed.sendCoin(httpnode, ownerAddress, fromAddress, 10L, 2,permissionKeyString); + Assert.assertFalse(HttpMethed.verificationResult(response)); + + logger.info("start permission id 2"); + response = HttpMethed.sendCoin(httpnode, ownerAddress, fromAddress, 12L, 2,permissionKeyActive); Assert.assertTrue(HttpMethed.verificationResult(response)); + response = HttpMethed.sendCoin(httpnode, ownerAddress, fromAddress, 12L, 0,permissionKeyActive); + Assert.assertFalse(HttpMethed.verificationResult(response)); + + response = HttpMethed.sendCoin(httpnode, ownerAddress, fromAddress, 11L, 1,permissionKeyActive); + Assert.assertFalse(HttpMethed.verificationResult(response)); + + response = HttpMethed.sendCoin(httpnode, ownerAddress, fromAddress, 11L, 3,permissionKeyString); + Assert.assertFalse(HttpMethed.verificationResult(response)); + } diff --git a/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestSendCoin001.java b/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestSendCoin001.java index 8ff7e5b3524..2238f7f749e 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestSendCoin001.java +++ b/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestSendCoin001.java @@ -60,8 +60,8 @@ public void test2GetTransactionByIdFromSolidity() { HttpMethed.printJsonContent(responseContent); String retString = responseContent.getString("ret"); JSONArray array = JSONArray.parseArray(retString); - Assert.assertEquals(HttpMethed.parseStringContent(array.get(0).toString()).getString( - "contractRet"), "SUCCESS"); + Assert.assertTrue(HttpMethed.parseStringContent(array.get(0).toString()).getString( + "contractRet") == null); Assert.assertTrue(responseContent.size() > 4); } @@ -90,6 +90,12 @@ public void test4GetTransactionsFromThisFromSolidity() { Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); responseContent = HttpMethed.parseResponseContent(response); HttpMethed.printJsonContent(responseContent); + JSONObject transactionObject = HttpMethed.parseStringContent(JSONArray.parseArray( + responseContent.getString("transaction")).get(0).toString()); + String retString = transactionObject.getString("ret"); + JSONArray array = JSONArray.parseArray(retString); + Assert.assertTrue(HttpMethed.parseStringContent(array.get(0).toString()) + .getString("contractRet") == null); Assert.assertTrue(responseContent.size() == 1); } @@ -103,6 +109,12 @@ public void test5GetTransactionsToThisFromSolidity() { Assert.assertEquals(response.getStatusLine().getStatusCode(), 200); responseContent = HttpMethed.parseResponseContent(response); HttpMethed.printJsonContent(responseContent); + JSONObject transactionObject = HttpMethed.parseStringContent( + JSONArray.parseArray(responseContent.getString("transaction")).get(0).toString()); + String retString = transactionObject.getString("ret"); + JSONArray array = JSONArray.parseArray(retString); + Assert.assertTrue(HttpMethed.parseStringContent(array.get(0).toString()).getString( + "contractRet") == null); Assert.assertTrue(responseContent.size() == 1); } diff --git a/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestSmartContract001.java b/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestSmartContract001.java index 0e85b7f8ef7..742b856df90 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestSmartContract001.java +++ b/src/test/java/stest/tron/wallet/dailybuild/http/HttpTestSmartContract001.java @@ -27,6 +27,12 @@ public class HttpTestSmartContract001 { ECKey ecKey2 = new ECKey(Utils.getRandom()); byte[] assetOwnerAddress = ecKey2.getAddress(); String assetOwnerKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); + + ECKey ecKey3 = new ECKey(Utils.getRandom()); + byte[] assetReceiverAddress = ecKey3.getAddress(); + String assetReceiverKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); + + String contractAddress; Long amount = 2048000000L; @@ -50,9 +56,12 @@ public void test1DeployContract() { PublicMethed.printAddress(assetOwnerKey); HttpMethed.waitToProduceOneBlock(httpnode); response = HttpMethed.sendCoin(httpnode, fromAddress, assetOwnerAddress, amount, testKey002); + response = HttpMethed.sendCoin(httpnode, fromAddress, assetReceiverAddress, amount, testKey002); Assert.assertTrue(HttpMethed.verificationResult(response)); HttpMethed.waitToProduceOneBlock(httpnode); //Create an asset issue + response = HttpMethed.freezeBalance(httpnode,assetOwnerAddress,100000000L,3,1,assetOwnerKey); + Assert.assertTrue(HttpMethed.verificationResult(response)); response = HttpMethed.assetIssue(httpnode, assetOwnerAddress, name, name, totalSupply, 1, 1, System.currentTimeMillis() + 5000, System.currentTimeMillis() + 50000000, 2, 3, description, url, 1000L, 1000L, assetOwnerKey); @@ -72,9 +81,20 @@ public void test1DeployContract() { String abi = Configuration.getByPath("testng.conf") .getString("abi.abi_ContractTrcToken001_transferTokenContract"); + long tokenValue = 100000; long callValue = 5000; + //This deploy is test too large call_token_value will made the witness node cpu 100% + /*response = HttpMethed.deployContractGetTxidWithTooBigLong(httpnode, + contractName, abi, code, 1000000L,1000000000L, 100, 11111111111111L, + callValue, Integer.parseInt(assetIssueId), tokenValue, assetOwnerAddress, assetOwnerKey); + responseContent = HttpMethed.parseResponseContent(response); + Assert.assertTrue(responseContent.getString("Error").contains("Overflow"));*/ + + + + String txid = HttpMethed.deployContractGetTxid(httpnode, contractName, abi, code, 1000000L, 1000000000L, 100, 11111111111111L, callValue, Integer.parseInt(assetIssueId), tokenValue, assetOwnerAddress, assetOwnerKey); @@ -117,8 +137,8 @@ public void test2GetContract() { @Test(enabled = true, description = "Trigger contract by http") public void test3TriggerContract() { - String hexFromAddress = ByteArray.toHexString(fromAddress); - String addressParam = "000000000000000000000000" + hexFromAddress.substring(2);//[0,3) + String hexReceiverAddress = ByteArray.toHexString(assetReceiverAddress); + String addressParam = "000000000000000000000000" + hexReceiverAddress.substring(2);//[0,3) String tokenIdParam = "00000000000000000000000000000000000000000000000000000000000" + Integer.toHexString(Integer.parseInt(assetIssueId)); @@ -127,10 +147,12 @@ public void test3TriggerContract() { logger.info(addressParam); logger.info(tokenIdParam); logger.info(tokenValueParam); + final Long beforeBalance = HttpMethed.getBalance(httpnode,assetOwnerAddress); String param = addressParam + tokenIdParam + tokenValueParam; + Long callValue = 10L; String txid = HttpMethed.triggerContractGetTxid(httpnode, assetOwnerAddress, contractAddress, "TransferTokenTo(address,trcToken,uint256)", - param, 1000000000L, 10L, Integer.parseInt(assetIssueId), 20L, assetOwnerKey); + param, 1000000000L, callValue, Integer.parseInt(assetIssueId), 20L, assetOwnerKey); HttpMethed.waitToProduceOneBlock(httpnode); //String txid = "49a30653d6e648da1e9a104b051b1b55c185fcaa0c2885405ae1d2fb258e3b3c"; @@ -141,6 +163,12 @@ public void test3TriggerContract() { Assert.assertEquals(txid, responseContent.getString("txID")); Assert.assertTrue(!responseContent.getString("raw_data").isEmpty()); Assert.assertTrue(!responseContent.getString("raw_data_hex").isEmpty()); + Long afterBalance = HttpMethed.getBalance(httpnode,assetOwnerAddress); + logger.info("beforeBalance: " + beforeBalance); + logger.info("afterBalance: " + afterBalance); + Assert.assertTrue(beforeBalance - afterBalance == callValue); + + response = HttpMethed.getTransactionInfoById(httpnode, txid); responseContent = HttpMethed.parseResponseContent(response); @@ -148,8 +176,13 @@ public void test3TriggerContract() { String receiptString = responseContent.getString("receipt"); Assert .assertEquals(HttpMethed.parseStringContent(receiptString).getString("result"), "SUCCESS"); - Assert.assertTrue(responseContent.getLong("fee") > 0); + Assert.assertTrue(HttpMethed.parseStringContent(receiptString).getLong("energy_usage") > 0); Assert.assertTrue(responseContent.getLong("blockNumber") > 0); + + response = HttpMethed.getAccount(httpnode, assetReceiverAddress); + responseContent = HttpMethed.parseResponseContent(response); + HttpMethed.printJsonContent(responseContent); + Assert.assertTrue(!responseContent.getString("assetV2").isEmpty()); } diff --git a/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction001.java b/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction001.java index 1f90941aea5..4813ef7c114 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction001.java +++ b/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction001.java @@ -3,6 +3,7 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Optional; import java.util.concurrent.TimeUnit; @@ -92,72 +93,22 @@ public void testInternalTransaction001() { .sendcoin(internalTxsAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, blockingStubFull)); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName = "FunctionSelector"; - String code = "6080604052610452806100136000396000f3006080604052600436106100325763ffffffff60e06" - + "0020a600035041663a408b1f58114610034578063bc07c44314610048575b005b610032600160a060020a03" - + "6004351661005f565b610032600160a060020a03600435166024356101f2565b600080600a61006c6102da5" - + "65b6040518091039082f080158015610087573d6000803e3d6000fd5b50905091506100946102da565b6040" - + "51809103906000f0801580156100b0573d6000803e3d6000fd5b50604051909150600160a060020a0382169" - + "060009060059082818181858883f193505050501580156100e6573d6000803e3d6000fd5b50604080517f78" - + "d7568f000000000000000000000000000000000000000000000000000000008152600160a060020a0385811" - + "66004830152600160248301529151918316916378d7568f9160448082019260009290919082900301818387" - + "803b15801561015257600080fd5b505af1158015610166573d6000803e3d6000fd5b5050604080517f78d75" - + "68f000000000000000000000000000000000000000000000000000000008152600160a060020a0387811660" - + "0483015260026024830152915191851693506378d7568f92506044808201926000929091908290030181838" - + "7803b1580156101d557600080fd5b505af11580156101e9573d6000803e3d6000fd5b50505050505050565b" - + "81600160a060020a03168160405180807f6e657742416e645472616e7366657228290000000000000000000" - + "000000000008152506011019050604051809103902060e060020a9004906040518263ffffffff1660e06002" - + "0a02815260040160006040518083038185885af193505050505081600160a060020a0316816001016040518" - + "0807f6e657742416e645472616e736665722829000000000000000000000000000000815250601101905060" - + "4051809103902060e060020a9004906040518263ffffffff1660e060020a028152600401600060405180830" - + "38185885af150505050505050565b60405161013c806102eb83390190560060806040526101298061001360" - + "00396000f300608060405260043610602f5763ffffffff60e060020a60003504166378d7568f81146031578" - + "063ab5ed15014605f575b005b348015603c57600080fd5b50602f73ffffffffffffffffffffffffffffffff" - + "ffffffff600435166024356077565b606560f8565b60408051918252519081900360200190f35b8173fffff" - + "fffffffffffffffffffffffffffffffffff168160405180807f6765745a65726f2829000000000000000000" - + "00000000000000000000000000008152506009019050604051809103902060e060020a9004906040518263f" - + "fffffff1660e060020a02815260040160006040518083038185885af150505050505050565b6001905600a1" - + "65627a7a723058205942f94fcb7cf8fb34f9b27c2704de9a2e8b677dca1e5e7c1b1a47fd9f0f8ff10029a16" - + "5627a7a723058207cf5e1689b0ebadac0eb1814174b5525584ccd0e9e84c8a278612a8b4497ec570029"; - String abi = "[{\"constant\":false,\"inputs\":[{\"name\":\"cAddr\",\"type\":\"address\"}],\"" - + "name\":\"test1\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"" - + "type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"cAddress\",\"type\"" - + ":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"test2\",\"outputs" - + "\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs" - + "\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"" - + "payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]"; + String filePath = "src/test/resources/soliditycode/" + + "contractInternalTransaction001testInternalTransaction001.sol"; + String contractName = "A"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, internalTxsAddress, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName1 = "FunctionSelector"; - String code1 = "6080604052610322806100136000396000f3006080604052600436106100325763ffffffff60e0" - + "60020a6000350416639f3f89dc8114610034578063fbf004e31461004e575b005b61003c610056565b60408" - + "051918252519081900360200190f35b61003c61005b565b600090565b6000806000600761006a6101aa565b" - + "6040518091039082f080158015610085573d6000803e3d6000fd5b50905091508173fffffffffffffffffff" - + "fffffffffffffffffffff1663ab5ed1506040518163ffffffff1660e060020a028152600401602060405180" - + "830381600087803b1580156100d557600080fd5b505af11580156100e9573d6000803e3d6000fd5b5050505" - + "06040513d60208110156100ff57600080fd5b506003905061010c6101aa565b6040518091039082f0801580" - + "15610127573d6000803e3d6000fd5b50905090508073ffffffffffffffffffffffffffffffffffffffff166" - + "3ab5ed1506040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801561" - + "017757600080fd5b505af115801561018b573d6000803e3d6000fd5b505050506040513d60208110156101a" - + "157600080fd5b50929392505050565b60405161013c806101bb833901905600608060405261012980610013" - + "6000396000f300608060405260043610602f5763ffffffff60e060020a60003504166378d7568f811460315" - + "78063ab5ed15014605f575b005b348015603c57600080fd5b50602f73ffffffffffffffffffffffffffffff" - + "ffffffffff600435166024356077565b606560f8565b60408051918252519081900360200190f35b8173fff" - + "fffffffffffffffffffffffffffffffffffff168160405180807f6765745a65726f28290000000000000000" - + "0000000000000000000000000000008152506009019050604051809103902060e060020a900490604051826" - + "3ffffffff1660e060020a02815260040160006040518083038185885af150505050505050565b6001905600" - + "a165627a7a723058205942f94fcb7cf8fb34f9b27c2704de9a2e8b677dca1e5e7c1b1a47fd9f0f8ff10029a" - + "165627a7a72305820e31e571ffe5382336fe7c2eeb9e13d0c3a86a5ee7ece66cb9a81fc734a9711830029"; - String abi1 = "[{\"constant\":false,\"inputs\":[],\"name\":\"getZero\",\"outputs\":[{\"name\"" - + ":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\"" - + ":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"newBAndTransfer\",\"" - + "outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability" - + "\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"" - + "stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"" - + "stateMutability\":\"payable\",\"type\":\"fallback\"}]"; + String contractName1 = "C"; + HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); + String code1 = retMap1.get("byteCode").toString(); + String abi1 = retMap1.get("abI").toString(); + byte[] contractAddress1 = PublicMethed .deployContract(contractName1, abi1, code1, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, @@ -204,32 +155,22 @@ public void testInternalTransaction002() { blockingStubFull)); PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName = "AContract"; - String code = "608060405260b8806100126000396000f300608060405260043610603e5763ffffffff7c0100000" - + "000000000000000000000000000000000000000000000000000600035041663bc07c44381146040575b005b" - + "603e73ffffffffffffffffffffffffffffffffffffffff6004351660243560405173fffffffffffffffffff" - + "fffffffffffffffffffff8316908290600081818185875af15050505050505600a165627a7a72305820d269" - + "019182dd18f94a6077c96e7432b646ac8958332e4e3f7f7d1686e3998d430029"; - String abi = "[{\"constant\":false,\"inputs\":[{\"name\":\"cAddress\",\"type\":\"address\"}," - + "{\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"test2\",\"outputs\":[],\"" - + "payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[]," - + "\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable" - + "\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]"; + + String filePath = "src/test/resources/soliditycode/" + + "contractInternalTransaction001testInternalTransaction002.sol"; + String contractName = "A"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, internalTxsAddress, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName1 = "FunctionSelector"; - String code1 = "608060405260898060116000396000f300608060405260043610603e5763ffffffff7c01000000" - + "000000000000000000000000000000000000000000000000006000350416639f3f89dc81146040575b005b6" - + "0466058565b60408051918252519081900360200190f35b6000905600a165627a7a7230582025bd5ceaa0a9" - + "3303800c2e39399a63822579b57aa6f2b20e8f0434737c87d9100029"; - String abi1 = "[{\"constant\":false,\"inputs\":[],\"name\":\"getZero\",\"outputs\":[{\"name\"" - + ":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\"" - + ":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\"" - + ":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"" - + "fallback\"}]"; + String contractName1 = "C"; + HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); + String code1 = retMap1.get("byteCode").toString(); + String abi1 = retMap1.get("abI").toString(); byte[] contractAddress1 = PublicMethed .deployContract(contractName1, abi1, code1, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, @@ -263,31 +204,12 @@ public void testInternalTransaction003() { .sendcoin(internalTxsAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, blockingStubFull)); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName = "AContract"; - String code = "608060405260008055610296806100176000396000f30060806040526004361060525763fffffff" - + "f7c010000000000000000000000000000000000000000000000000000000060003504166312065fe0811460" - + "575780634e70b1dc14607b5780638a4068dd14608d575b600080fd5b348015606257600080fd5b506069609" - + "5565b60408051918252519081900360200190f35b348015608657600080fd5b506069609a565b609360a056" - + "5b005b303190565b60005481565b6000600a60aa60ca565b6040518091039082f08015801560c4573d60008" - + "03e3d6000fd5b50505050565b604051610190806100db833901905600608060405260008055610179806100" - + "176000396000f3006080604052600436106100615763ffffffff7c010000000000000000000000000000000" - + "000000000000000000000000060003504166312065fe081146100635780631d1537e51461008a5780632612" - + "1ff0146100bd5780634e70b1dc146100d9575b005b34801561006f57600080fd5b506100786100ee565b604" - + "08051918252519081900360200190f35b34801561009657600080fd5b5061006173ffffffffffffffffffff" - + "ffffffffffffffffffff6004351660243515156100f3565b6100c5610142565b60408051911515825251908" - + "1900360200190f35b3480156100e557600080fd5b50610078610147565b303190565b60405173ffffffffff" - + "ffffffffffffffffffffffffffffff83169060009060019082818181858883f193505050501580156101325" - + "73d6000803e3d6000fd5b50801561013e57600080fd5b5050565b600190565b600054815600a165627a7a72" - + "30582044b8a80ea9a16b7b5f99c3ce976d68790ee8ec7cd846605b6814a20b7e5336a10029a165627a7a723" - + "05820a9269578e4975c55cc3900c6ac88e61c78e3a0762f15197f522a641d232f21f00029"; - String abi = "[{\"constant\":false,\"inputs\":[],\"name\":\"getBalance\",\"outputs\":[{\"name" - + "\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"" - + "type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"num\",\"outputs\":[{" - + "\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"" - + "type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"transfer\",\"outputs" - + "\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"}," - + "{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"" - + "constructor\"}]"; + String filePath = "src/test/resources/soliditycode/" + + "contractInternalTransaction001testInternalTransaction003.sol"; + String contractName = "A"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, internalTxsAddress, blockingStubFull); @@ -321,53 +243,21 @@ public void testInternalTransaction004() { blockingStubFull)); PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName = "AAContract"; - String code = "608060405260d7806100126000396000f30060806040526004361060485763ffffffff7c0100000" - + "00000000000000000000000000000000000000000000000000060003504166312065fe08114604a578063db" - + "c1f22614606e575b005b348015605557600080fd5b50605c608d565b6040805191825251908190036020019" - + "0f35b604873ffffffffffffffffffffffffffffffffffffffff600435166092565b303190565b8073ffffff" - + "ffffffffffffffffffffffffffffffffff16ff00a165627a7a723058206309c0dfcd62ddcfcef8080e55a41" - + "e63ffa98b9ba2c226c1d47ec9f047d77efe0029"; - String abi = "[{\"constant\":true,\"inputs\":[],\"name\":\"getBalance\",\"outputs\":[{\"name\"" - + ":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":" - + "\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"" - + "address\"}],\"name\":\"suicide\",\"outputs\":[],\"payable\":true,\"stateMutability\":" - + "\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\"" - + ":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable" - + "\",\"type\":\"fallback\"}]"; + String filePath = "src/test/resources/soliditycode/" + + "contractInternalTransaction001testInternalTransaction004.sol"; + String contractName = "A"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, internalTxsAddress, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName1 = "FunctionSelector"; - String code1 = "608060405234801561001057600080fd5b50610339806100206000396000f30060806040526004" - + "361061003d5763ffffffff60e060020a6000350416630567e83e811461004257806312065fe01461006b578" - + "0632bb685bc14610092575b600080fd5b61006973ffffffffffffffffffffffffffffffffffffffff600435" - + "811690602435166100a7565b005b34801561007757600080fd5b5061008061015d565b60408051918252519" - + "081900360200190f35b34801561009e57600080fd5b50610069610162565b8173ffffffffffffffffffffff" - + "ffffffffffffffffff1660405180807f7375696369646528616464726573732900000000000000000000000" - + "0000000008152506010019050604051809103902060e060020a9004306040518263ffffffff1660e060020a" - + "028152600401808273ffffffffffffffffffffffffffffffffffffffff1673fffffffffffffffffffffffff" - + "fffffffffffffff1681526020019150506000604051808303816000875af1505050505050565b303190565b" - + "600061016c610215565b604051809103906000f080158015610188573d6000803e3d6000fd5b50604080517" - + "fdbc1f226000000000000000000000000000000000000000000000000000000008152306004820152905191" - + "925073ffffffffffffffffffffffffffffffffffffffff83169163dbc1f2269160248082019260009290919" - + "082900301818387803b1580156101fa57600080fd5b505af115801561020e573d6000803e3d6000fd5b5050" - + "505050565b60405160e980610225833901905600608060405260d7806100126000396000f30060806040526" - + "004361060485763ffffffff7c01000000000000000000000000000000000000000000000000000000006000" - + "3504166312065fe08114604a578063dbc1f22614606e575b005b348015605557600080fd5b50605c608d565" - + "b60408051918252519081900360200190f35b604873ffffffffffffffffffffffffffffffffffffffff6004" - + "35166092565b303190565b8073ffffffffffffffffffffffffffffffffffffffff16ff00a165627a7a72305" - + "8206309c0dfcd62ddcfcef8080e55a41e63ffa98b9ba2c226c1d47ec9f047d77efe0029a165627a7a723058" - + "20021bc52f0b541c5905d76fc09d966c733e59bdabd3004dd70b14fd8f7ba4b64e0029"; - String abi1 = "[{\"constant\":false,\"inputs\":[{\"name\":\"contractAddres\",\"type\":\"" - + "address\"},{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":\"kill\",\"" - + "outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"}," - + "{\"constant\":true,\"inputs\":[],\"name\":\"getBalance\",\"outputs\":[{\"name\":\"\"," - + "\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"" - + "function\"},{\"constant\":false,\"inputs\":[],\"name\":\"kill2\",\"outputs\":[],\"" - + "payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"; + String contractName1 = "B"; + HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); + String code1 = retMap1.get("byteCode").toString(); + String abi1 = retMap1.get("abI").toString(); byte[] contractAddress1 = PublicMethed .deployContract(contractName1, abi1, code1, "", maxFeeLimit, 0, 100, null, testKeyForinternalTxsAddress, @@ -436,48 +326,12 @@ public void testInternalTransaction005() { .sendcoin(internalTxsAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, blockingStubFull)); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName = "AAContract"; - String code = "608060405261056d806100136000396000f3006080604052600436106100565763ffffffff7c010" - + "000000000000000000000000000000000000000000000000000000060003504166312065fe0811461005857" - + "806366e41cb71461007f5780636b59084d14610087575b005b34801561006457600080fd5b5061006d61008" - + "f565b60408051918252519081900360200190f35b610056610094565b6100566101fe565b303190565b6000" - + "600a6100a0610337565b6040518091039082f0801580156100bb573d6000803e3d6000fd5b5090509050807" - + "3ffffffffffffffffffffffffffffffffffffffff1663ae73948b60006040518263ffffffff167c01000000" - + "000000000000000000000000000000000000000000000000000281526004018082151515158152602001915" - + "050602060405180830381600087803b15801561013457600080fd5b505af1158015610148573d6000803e3d" - + "6000fd5b505050506040513d602081101561015e57600080fd5b5050604080517fae73948b0000000000000" - + "0000000000000000000000000000000000000000000815260016004820152905173ffffffffffffffffffff" - + "ffffffffffffffffffff83169163ae73948b9160248083019260209291908290030181600087803b1580156" - + "101cf57600080fd5b505af11580156101e3573d6000803e3d6000fd5b505050506040513d60208110156101" - + "f957600080fd5b505050565b6000600a61020a610347565b6040518091039082f080158015610225573d600" - + "0803e3d6000fd5b50604080517f89dab7320000000000000000000000000000000000000000000000000000" - + "00008152600060048201819052915192945073ffffffffffffffffffffffffffffffffffffffff851693506" - + "389dab732926024808301939282900301818387803b15801561029657600080fd5b505af11580156102aa57" - + "3d6000803e3d6000fd5b5050604080517f89dab732000000000000000000000000000000000000000000000" - + "00000000000815260016004820152905173ffffffffffffffffffffffffffffffffffffffff851693506389" - + "dab7329250602480830192600092919082900301818387803b15801561031c57600080fd5b505af11580156" - + "10330573d6000803e3d6000fd5b5050505050565b60405161010f8061035783390190565b60405160dc8061" - + "046683390190560060806040526000805560f9806100166000396000f300608060405260043610605c5763f" - + "fffffff7c0100000000000000000000000000000000000000000000000000000000600035041663890eba68" - + "8114605e5780639f3f89dc146082578063ae73948b146088578063f9633930146093575b005b34801560695" - + "7600080fd5b50607060a5565b60408051918252519081900360200190f35b607060ab565b60706004351515" - + "60b0565b348015609e57600080fd5b50607060c7565b60005481565b600090565b600160009081558115156" - + "0c257600080fd5b919050565b600054905600a165627a7a72305820cd266b203bcc52675dc65abb8d7e600e" - + "ed9c9c4762afef89f206085ec34ecde40029608060405260ca806100126000396000f300608060405260043" - + "61060525763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504" - + "166312065fe08114605457806389dab732146078578063ab5ed150146083575b005b348015605f57600080f" - + "d5b5060666089565b60408051918252519081900360200190f35b60526004351515608e565b60666099565b" - + "303190565b801515609657fe5b50565b6001905600a165627a7a72305820bf93d38249d3b2ebdbc68ea5d13" - + "3ad2e8bf51f22c6f1f6de4c2d7b2fc285b1040029a165627a7a72305820d4e383d1572be1877cd1d252c6a8" - + "efa74a730697d5b3743b2f5c1c9f0f3a96930029"; - String abi = "[{\"constant\":true,\"inputs\":[],\"name\":\"getBalance\",\"outputs\":[{\"name" - + "\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\"" - + ":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"test2\",\"outputs\":[],\"" - + "payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":" - + "false,\"inputs\":[],\"name\":\"test1\",\"outputs\":[],\"payable\":true,\"" - + "stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true," - + "\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"" - + "stateMutability\":\"payable\",\"type\":\"fallback\"}]"; + String filePath = "src/test/resources/soliditycode/" + + "contractInternalTransaction001testInternalTransaction005.sol"; + String contractName = "A"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, internalTxsAddress, blockingStubFull); @@ -546,48 +400,12 @@ public void testInternalTransaction006() { .sendcoin(internalTxsAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, blockingStubFull)); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName = "AAContract"; - String code = "608060405261056c806100136000396000f3006080604052600436106100565763ffffffff7c010" - + "000000000000000000000000000000000000000000000000000000060003504166312065fe0811461005857" - + "806366e41cb71461007f5780636b59084d14610087575b005b34801561006457600080fd5b5061006d61008" - + "f565b60408051918252519081900360200190f35b610056610094565b6100566101fd565b303190565b6000" - + "600a6100a0610336565b6040518091039082f0801580156100bb573d6000803e3d6000fd5b50604080517fa" - + "e73948b00000000000000000000000000000000000000000000000000000000815260016004820152905191" - + "935073ffffffffffffffffffffffffffffffffffffffff8416925063ae73948b91602480830192602092919" - + "08290030181600087803b15801561012f57600080fd5b505af1158015610143573d6000803e3d6000fd5b50" - + "5050506040513d602081101561015957600080fd5b5050604080517fae73948b00000000000000000000000" - + "0000000000000000000000000000000008152600060048201819052915173ffffffffffffffffffffffffff" - + "ffffffffffffff84169263ae73948b92602480820193602093909283900390910190829087803b158015610" - + "1ce57600080fd5b505af11580156101e2573d6000803e3d6000fd5b505050506040513d60208110156101f8" - + "57600080fd5b505050565b6000600a610209610346565b6040518091039082f080158015610224573d60008" - + "03e3d6000fd5b50604080517f89dab732000000000000000000000000000000000000000000000000000000" - + "00815260016004820152905191935073ffffffffffffffffffffffffffffffffffffffff841692506389dab" - + "73291602480830192600092919082900301818387803b15801561029757600080fd5b505af11580156102ab" - + "573d6000803e3d6000fd5b5050604080517f89dab7320000000000000000000000000000000000000000000" - + "00000000000008152600060048201819052915173ffffffffffffffffffffffffffffffffffffffff861694" - + "506389dab73293506024808301939282900301818387803b15801561031b57600080fd5b505af1158015610" - + "32f573d6000803e3d6000fd5b5050505050565b60405161010f8061035683390190565b60405160dc806104" - + "6583390190560060806040526000805560f9806100166000396000f300608060405260043610605c5763fff" - + "fffff7c0100000000000000000000000000000000000000000000000000000000600035041663890eba6881" - + "14605e5780639f3f89dc146082578063ae73948b146088578063f9633930146093575b005b3480156069576" - + "00080fd5b50607060a5565b60408051918252519081900360200190f35b607060ab565b6070600435151560" - + "b0565b348015609e57600080fd5b50607060c7565b60005481565b600090565b6001600090815581151560c" - + "257600080fd5b919050565b600054905600a165627a7a72305820f1ef4e8b8396ad427c81068bbcdedeb60b" - + "0ec73347e834cdd68c00391c3e5bf30029608060405260ca806100126000396000f30060806040526004361" - + "060525763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416" - + "6312065fe08114605457806389dab732146078578063ab5ed150146083575b005b348015605f57600080fd5" - + "b5060666089565b60408051918252519081900360200190f35b60526004351515608e565b60666099565b30" - + "3190565b801515609657fe5b50565b6001905600a165627a7a72305820e177520d8acebf221bbf1f20e1eef" - + "78bde9f5d933170fa03de0dac42e247b3730029a165627a7a72305820d2d8cfbc2d7f6f9ed5dd8f606b63d2" - + "564ad4bae7f2653e5cb86dc2637a44219f0029"; - String abi = "[{\"constant\":true,\"inputs\":[],\"name\":\"getBalance\",\"outputs\":[{\"name" - + "\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type" - + "\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"test2\",\"outputs\":[]," - + "\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\"" - + ":false,\"inputs\":[],\"name\":\"test1\",\"outputs\":[],\"payable\":true,\"" - + "stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true," - + "\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"" - + "stateMutability\":\"payable\",\"type\":\"fallback\"}]"; + String filePath = "src/test/resources/soliditycode/" + + "contractInternalTransaction001testInternalTransaction006.sol"; + String contractName = "A"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, internalTxsAddress, blockingStubFull); diff --git a/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction002.java b/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction002.java index 0fbb09e5a13..e6f6f0926e8 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction002.java +++ b/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction002.java @@ -3,6 +3,7 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Optional; import java.util.concurrent.TimeUnit; @@ -93,51 +94,22 @@ public void test1InternalTransaction007() { blockingStubFull)); PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName = "AAContract"; - String code = "60806040526102eb806100136000396000f3006080604052600436106100325763fff" - + "fffff60e060020a600035041663a408b1f58114610034578063bc07c44314610055575b005b61003273fff" - + "fffffffffffffffffffffffffffffffffffff60043516610079565b61003273fffffffffffffffffffffff" - + "fffffffffffffffff60043516602435610176565b600080600a6100866101f7565b6040518091039082f08" - + "01580156100a1573d6000803e3d6000fd5b50905091506100ae6101f7565b604051809103906000f080158" - + "0156100ca573d6000803e3d6000fd5b5060405190915073fffffffffffffffffffffffffffffffffffffff" - + "f82169060009060059082818181858883f1935050505015801561010d573d6000803e3d6000fd5b508073f" - + "fffffffffffffffffffffffffffffffffffffff16639498d95f6040518163ffffffff1660e060020a02815" - + "2600401600060405180830381600087803b15801561015957600080fd5b505af115801561016d573d60008" - + "03e3d6000fd5b50505050505050565b8173ffffffffffffffffffffffffffffffffffffffff16816040518" - + "0807f6e657742416e645472616e73666572282900000000000000000000000000000081525060110190506" - + "04051809103902060e060020a9004906040518263ffffffff1660e060020a0281526004016000604051808" - + "3038185885af150505050505050565b60405160b980610207833901905600608060405260a780610012600" - + "0396000f30060806040526004361060485763ffffffff7c010000000000000000000000000000000000000" - + "00000000000000000006000350416639498d95f8114604a578063ab5ed15014605c575b005b34801560555" - + "7600080fd5b5060486074565b60626076565b60408051918252519081900360200190f35bfe5b600190560" - + "0a165627a7a7230582070fad514bdeed26e16c5efaf07d75624c5b7b62c36d192d4d9c74b202bec4a86002" - + "9a165627a7a72305820ae89f916945e45b1f28045306834e6243e7b6a4313c941865f0d71e4f8bd874a0029"; - String abi = "[{\"constant\":false,\"inputs\":[{\"name\":\"cAddr\",\"type\":\"address\"}],\"" - + "name\":\"test1\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"" - + "type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"cAddress\",\"type\"" - + ":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"test2\",\"" - + "outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"}," - + "{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor" - + "\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]"; + String filePath = "src/test/resources/soliditycode/" + + "contractInternalTransaction002test1InternalTransaction007.sol"; + String contractName = "A"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, internalTxsAddress, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName1 = "AAContract"; - String code1 = "6080604052609f806100126000396000f30060806040526004361060485763ffffffff7c010000" - + "00000000000000000000000000000000000000000000000000006000350416639f3f89dc811460" - + "4a578063fbf004e3146062575b005b60506068565b60408051918252519081900360200190f35b" - + "6050606d565b600090565b60008080fd00a165627a7a72305820b33557647706277de1253c89587" - + "165fb969c5ceb2483368d1c7cb7ed5e880b200029"; - String abi1 = "[{\"constant\":false,\"inputs\":[],\"name\":\"getZero\",\"outputs\":[{\"name\"" - + ":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\"" - + ":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"newBAndTransfer\",\"outputs" - + "\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"" - + "payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability" - + "\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"" - + "payable\",\"type\":\"fallback\"}]"; + String contractName1 = "C"; + HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); + String code1 = retMap1.get("byteCode").toString(); + String abi1 = retMap1.get("abI").toString(); byte[] contractAddress1 = PublicMethed .deployContract(contractName1, abi1, code1, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, @@ -215,74 +187,21 @@ public void test2InternalTransaction008() { blockingStubFull)); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName = "AAContract"; - String code = "60806040526104b9806100136000396000f3006080604052600436106100535763fffffff" - + "f60e060020a60003504166312065fe081146100555780631ef57f9c1461007c578063a4c1aa" - + "8114610093578063d2fbea8a146100aa578063f2179191146100c1575b005b3480156100615760" - + "0080fd5b5061006a6100d8565b60408051918252519081900360200190f35b610053600160a060" - + "020a03600435166024356100dd565b610053600160a060020a03600435166024356101b9565b61" - + "0053600160a060020a0360043516602435610295565b610053600160a060020a03600435166024" - + "35610371565b303190565b6040805160008051602061046e833981519152815281519081900360" - + "1201812063ffffffff60e060020a918290049081169091028252600060048301819052925160016" - + "0a060020a038616939192620f42409286926024808401938290030181858988f1505060408051600" - + "08051602061046e8339815191528152815190819003601201812063ffffffff60e060020a9182900" - + "49081169091028252600160048301529151600160a060020a0389169650919450620f42409350869" - + "2506024808201926000929091908290030181858988f15050505050505050565b604080516000805" - + "1602061044e8339815191528152815190819003601501812063ffffffff60e060020a91829004908116" - + "9091028252600160048301529151600160a060020a0385169291620f424091859160248082019260009" - + "29091908290030181858988f150506040805160008051602061044e833981519152815281519081900360" - + "1501812063ffffffff60e060020a9182900490811690910282526000600483018190529251600160a06002" - + "0a038a169750909550620f42409450879350602480830193928290030181858988f15050505050505050" - + "565b6040805160008051602061046e8339815191528152815190819003601201812063ffffffff60e0600" - + "20a918290049081169091028252600160048301529151600160a060020a0385169291620f424091859160" - + "24808201926000929091908290030181858988f150506040805160008051602061046e8339815191528152" - + "815190819003601201812063ffffffff60e060020a91829004908116909102825260006004830181905292" - + "51600160a060020a038a169750909550620f42409450879350602480830193928290030181858988f15050" - + "505050505050565b6040805160008051602061044e8339815191528152815190819003601501812063ffff" - + "ffff60e060020a9182900490811690910282526000600483018190529251600160a060020a0386169391926" - + "20f42409286926024808401938290030181858988f150506040805160008051602061044e833981519152" - + "8152815190819003601501812063ffffffff60e060020a9182900490811690910282526001600483015291" - + "51600160a060020a0389169650919450620f42409350869250602480820192600092909190829003018185" - + "8988f1505050505050505056006e657742416e645472616e7366657228626f6f6c29000000000000000000" - + "000063616c6c434765745a65726f28626f6f6c290000000000000000000000000000a165627a7a72305820" - + "d3c23901c8790e2c6c8f449919c8903a53644ff11abbe75058453662189331a50029"; - String abi = "[{\"constant\":true,\"inputs\":[],\"name\":\"getBalance\",\"outputs\":[{\"" - + "name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\"" - + ",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"bAddress\",\"" - + "type\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"testAssert" - + "\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function" - + "\"},{\"constant\":false,\"inputs\":[{\"name\":\"cAddress\",\"type\":\"address\"},{\"" - + "name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"testtRequire2\",\"outputs\":[],\"" - + "payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":" - + "false,\"inputs\":[{\"name\":\"bAddress\",\"type\":\"address\"},{\"name\":\"amount\"," - + "\"type\":\"uint256\"}],\"name\":\"testAssert1\",\"outputs\":[],\"payable\":true,\"" - + "stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\"" - + ":[{\"name\":\"cAddress\",\"type\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256" - + "\"}],\"name\":\"testRequire\",\"outputs\":[],\"payable\":true,\"stateMutability\":" - + "\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability" - + "\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"" - + "payable\",\"type\":\"fallback\"}]"; + String filePath = "src/test/resources/soliditycode/" + + "contractInternalTransaction002test2InternalTransaction008.sol"; + String contractName = "A"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, internalTxsAddress, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName1 = "BContract"; - String code1 = "608060405260ca806100126000396000f30060806040526004361060525763ffffffff7c01" - + "0000000000000000000000000000000000000000000000000000000060003504166312065fe0" - + "8114605457806389dab732146078578063ab5ed150146083575b005b348015605f57600080fd5" - + "b5060666089565b60408051918252519081900360200190f35b60526004351515608e565b606660" - + "99565b303190565b801515609657fe5b50565b6001905600a165627a7a7230582058f00f" - + "4bacb7ee761be9d22cf61ccebb340613a9a8670d8492aae0c7f5ec63440029"; - String abi1 = "[{\"constant\":true,\"inputs\":[],\"name\":\"getBalance\",\"outputs\":[{\"name" - + "\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type" - + "\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"success\",\"type\":\"" - + "bool\"}],\"name\":\"callCGetZero\",\"outputs\":[],\"payable\":true,\"stateMutability" - + "\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":" - + "\"getOne\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"" - + "stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":" - + "true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true," - + "\"stateMutability\":\"payable\",\"type\":\"fallback\"}]"; + String contractName1 = "B"; + HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); + String code1 = retMap1.get("byteCode").toString(); + String abi1 = retMap1.get("abI").toString(); byte[] contractAddress1 = PublicMethed .deployContract(contractName1, abi1, code1, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, @@ -314,26 +233,10 @@ public void test2InternalTransaction008() { Assert.assertEquals("call", note1); Assert.assertTrue(1 == vaule1); Assert.assertTrue(1 == vaule2); - String contractName2 = "BContract"; - String code2 = "60806040526000805560f9806100166000396000f300608060405260043610605c5763f" - + "fffffff7c01000000000000000000000000000000000000000000000000000000006000350416" - + "63890eba688114605e5780639f3f89dc146082578063ae73948b146088578063f963393014609" - + "3575b005b348015606957600080fd5b50607060a5565b60408051918252519081900360200190f" - + "35b607060ab565b6070600435151560b0565b348015609e57600080fd5b50607060c7565b600054" - + "81565b600090565b6001600090815581151560c257600080fd5b919050565b600054905600a165627" - + "a7a7230582008a9178816b974b70bfec88feaa4049844aac312f7fa6983b9481a597f52ae400029"; - String abi2 = "[{\"constant\":true,\"inputs\":[],\"name\":\"flag\",\"outputs\":[{\"name\":\"" - + "\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"" - + "function\"},{\"constant\":false,\"inputs\":[],\"name\":\"getZero\",\"outputs\":[{\"" - + "name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\"" - + ",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"success\",\"" - + "type\":\"bool\"}],\"name\":\"newBAndTransfer\",\"outputs\":[{\"name\":\"\",\"type" - + "\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"" - + "function\"},{\"constant\":false,\"inputs\":[],\"name\":\"getFlag\",\"outputs\":" - + "[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"" - + "nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability" - + "\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":" - + "\"payable\",\"type\":\"fallback\"}]"; + String contractName2 = "C"; + HashMap retMap2 = PublicMethed.getBycodeAbi(filePath, contractName2); + String code2 = retMap2.get("byteCode").toString(); + String abi2 = retMap2.get("abI").toString(); byte[] contractAddress2 = PublicMethed .deployContract(contractName2, abi2, code2, "", maxFeeLimit, @@ -424,121 +327,39 @@ public void test3InternalTransaction009() { .sendcoin(internalTxsAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, blockingStubFull)); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName = "AAContract"; - String code = "608060405261043b806100136000396000f3006080604052600436106100405763ffffffff7" - + "c0100000000000000000000000000000000000000000000000000000000600035041663baf8" - + "267c8114610042575b005b61004073ffffffffffffffffffffffffffffffffffffffff60043581169" - + "0602435811690604435166000600a6100766101fd565b6040518091039082f080158015610091573d6" - + "000803e3d6000fd5b5060405190925073ffffffffffffffffffffffffffffffffffffffff831691506" - + "0009060059082818181858883f193505050501580156100d5573d6000803e3d6000fd5b50604080517" - + "f78d7568f00000000000000000000000000000000000000000000000000000000815273fffffffffff" - + "fffffffffffffffffffffffffffff8681166004830152600160248301529151918316916378d7568f9" - + "160448082019260009290919082900301818387803b15801561014e57600080fd5b505af1158015610" - + "162573d6000803e3d6000fd5b5050604080517fc3ad2c4f00000000000000000000000000000000000" - + "000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff878116600483015286" - + "811660248301529151918516935063c3ad2c4f925060448082019260009290919082900301818387803b15" - + "80156101df57600080fd5b505af11580156101f3573d6000803e3d6000fd5b5050505050505050565b60" - + "40516102028061020e83390190560060806040526101ef806100136000396000f30060806040526004361" - + "06100325763ffffffff60e060020a60003504166378d7568f8114610034578063c3ad2c4f14610065575b" - + "005b34801561004057600080fd5b5061003273ffffffffffffffffffffffffffffffffffffffff60043516" - + "60243561008c565b61003273ffffffffffffffffffffffffffffffffffffffff6004358116906024351661" - + "010d565b8173ffffffffffffffffffffffffffffffffffffffff168160405180807f6765745a65726f28" - + "2900000000000000000000000000000000000000000000008152506009019050604051809103902060e0" - + "60020a9004906040518263ffffffff1660e060020a02815260040160006040518083038185885af150505" - + "050505050565b8173ffffffffffffffffffffffffffffffffffffffff1660405180807f73756963696465" - + "286164647265737329000000000000000000000000000000008152506010019050604051809103902060e" - + "060020a9004306040518263ffffffff1660e060020a028152600401808273ffffffffffffffffffffffff" - + "ffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060006040" - + "51808303816000875af15050505050505600a165627a7a72305820af0751029fe4b41ae4df4997665234" - + "c6b6ff8a83721d80197456cbb61acae5290029a165627a7a72305820e2ad36db09c43d4e1d9f81" - + "a6da08b387d0e3c7d98e98def9e39bd4229ba6633f0029"; - String abi = "[{\"constant\":false,\"inputs\":[{\"name\":\"cAddr\",\"type\":\"address\"}" - + ",{\"name\":\"dcontract\",\"type\":\"address\"},{\"name\":\"baddress\",\"type\":\"" - + "address\"}],\"name\":\"test1\",\"outputs\":[],\"payable\":true,\"stateMutability\"" - + ":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"" - + "stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"" - + "stateMutability\":\"payable\",\"type\":\"fallback\"}]"; - + String filePath = "src/test/resources/soliditycode/" + + "contractInternalTransaction002test3InternalTransaction009.sol"; + String contractName = "A"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, internalTxsAddress, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName1 = "BContract"; - String code1 = "60806040526101ef806100136000396000f3006080604052600436106100325763fff" - + "fffff60e060020a60003504166378d7568f8114610034578063c3ad2c4f14610065575b005b3" - + "4801561004057600080fd5b5061003273ffffffffffffffffffffffffffffffffffffffff600435" - + "1660243561008c565b61003273ffffffffffffffffffffffffffffffffffffffff600435811690" - + "6024351661010d565b8173ffffffffffffffffffffffffffffffffffffffff168160405180807f67" - + "65745a65726f2829000000000000000000000000000000000000000000000081525060090190506040" - + "51809103902060e060020a9004906040518263ffffffff1660e060020a02815260040160006040" - + "518083038185885af150505050505050565b8173ffffffffffffffffffffffffffffffffffff" - + "ffff1660405180807f73756963696465286164647265737329000000000000000000000000000000" - + "008152506010019050604051809103902060e060020a9004306040518263ffffffff1660e060020a" - + "028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffff" - + "ffffffffffffffffffffff1681526020019150506000604051808303816000875af1505050505050" - + "5600a165627a7a72305820af0751029fe4b41ae4df4997665234c6b6ff8a83721d8019745" - + "6cbb61acae5290029"; - String abi1 = "[{\"constant\":false,\"inputs\":[{\"name\":\"cAddress\",\"type\":" - + "\"address\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"callCGetZero" - + "\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type" - + "\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"contractAddres\"," - + "\"type\":\"address\"},{\"name\":\"toAddress\",\"type\":\"address\"}],\"name\":" - + "\"getOne\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"" - + "type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"" - + "payable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":" - + "\"payable\",\"type\":\"fallback\"}]"; + String contractName1 = "B"; + HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); + String code1 = retMap1.get("byteCode").toString(); + String abi1 = retMap1.get("abI").toString(); byte[] contractAddress1 = PublicMethed .deployContract(contractName1, abi1, code1, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, internalTxsAddress, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName2 = "CContract"; - String code2 = "60806040526102fe806100136000396000f30060806040526004361060485763ffffffff7c0" - + "1000000000000000000000000000000000000000000000000000000006000350416639f3f89dc811" - + "4604a578063fbf004e3146062575b005b60506068565b60408051918252519081900360200190f35b" - + "6048606d565b600090565b6000806007607860c0565b6040518091039082f0801580156092573d60008" - + "03e3d6000fd5b50905091506003609f60c0565b6040518091039082f08015801560b9573d6000803e3d600" - + "0fd5b5050505050565b604051610202806100d183390190560060806040526101ef8061001360003960" - + "00f3006080604052600436106100325763ffffffff60e060020a60003504166378d7568f811461003457" - + "8063c3ad2c4f14610065575b005b34801561004057600080fd5b5061003273fffffffffffffffffffff" - + "fffffffffffffffffff6004351660243561008c565b61003273ffffffffffffffffffffffffffffffffff" - + "ffffff6004358116906024351661010d565b8173ffffffffffffffffffffffffffffffffffffffff1681" - + "60405180807f6765745a65726f28290000000000000000000000000000000000000000000000815250" - + "6009019050604051809103902060e060020a9004906040518263ffffffff1660e060020a02815260040" - + "160006040518083038185885af150505050505050565b8173ffffffffffffffffffffffffffffffffff" - + "ffffff1660405180807f73756963696465286164647265737329000000000000000000000000000000008" - + "152506010019050604051809103902060e060020a9004306040518263ffffffff1660e060020a02815260" - + "0401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffff" - + "ffffffffffff1681526020019150506000604051808303816000875af15050505050505600a165627a7a723" - + "05820af0751029fe4b41ae4df4997665234c6b6ff8a83721d80197456cbb61acae5290029a165627a7" - + "a723058206134d73dbfb7016f931ef993f8555909949ce40fb312f52a2ac07e18e906c4da0029"; - String abi2 = "[{\"constant\":false,\"inputs\":[],\"name\":\"getZero\",\"outputs\":" - + "[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":" - + "\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\"" - + ":\"newBAndTransfer\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"" - + "payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"" - + "stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true," - + "\"stateMutability\":\"payable\",\"type\":\"fallback\"}]"; + String contractName2 = "C"; + HashMap retMap2 = PublicMethed.getBycodeAbi(filePath, contractName2); + String code2 = retMap2.get("byteCode").toString(); + String abi2 = retMap2.get("abI").toString(); byte[] contractAddress2 = PublicMethed .deployContract(contractName2, abi2, code2, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, internalTxsAddress, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName3 = "DContract"; - String code3 = "608060405260d7806100126000396000f30060806040526004361060485763ffffffff7c01" - + "0000000000000000000000000000000000000000000000000000000060003504166312065fe0" - + "8114604a578063dbc1f22614606e575b005b348015605557600080fd5b50605c608d565b60408" - + "051918252519081900360200190f35b604873ffffffffffffffffffffffffffffffffffffffff6" - + "00435166092565b303190565b8073ffffffffffffffffffffffffffffffffffffffff16ff00a165" - + "627a7a72305820680c0350e5d8f60ee6f96f196b47870f00614fa9c742dfc18735d89ad0ef62ba0029"; - String abi3 = "[{\"constant\":true,\"inputs\":[],\"name\":\"getBalance\",\"outputs\"" - + ":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\"" - + ":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"" - + "toAddress\",\"type\":\"address\"}],\"name\":\"suicide\",\"outputs\":[],\"payable\"" - + ":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"" - + "payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}," - + "{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]"; + String contractName3 = "D"; + HashMap retMap3 = PublicMethed.getBycodeAbi(filePath, contractName3); + String code3 = retMap3.get("byteCode").toString(); + String abi3 = retMap3.get("abI").toString(); byte[] contractAddress3 = PublicMethed .deployContract(contractName3, abi3, code3, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, @@ -600,122 +421,12 @@ public void test4InternalTransaction010() { .sendcoin(internalTxsAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, blockingStubFull)); PublicMethed.waitProduceNextBlock(blockingStubFull); - - String contractName = "AAContract"; - String code = "6080604052600080556110d3806100176000396000f3006080604052600436106100615763" - + "ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166" - + "312065fe08114610066578063248c44e81461008d5780634e70b1dc146100975780638a4068dd14" - + "6100ac575b600080fd5b34801561007257600080fd5b5061007b6100b4565b60408051918252519" - + "081900360200190f35b6100956100b9565b005b3480156100a357600080fd5b5061007b610efb565b" - + "610095610f01565b303190565b60016100c3610f07565b6040518091039082f0801580156100de573d60008" - + "03e3d6000fd5b5090505060016100ec610f07565b6040518091039082f080158015610107573d600080" - + "3e3d6000fd5b509050506001610115610f07565b6040518091039082f080158015610130573d6000803e3" - + "d6000fd5b50905050600161013e610f07565b6040518091039082f080158015610159573d6000803e3d60" - + "00fd5b509050506001610167610f07565b6040518091039082f080158015610182573d6000803e3d6000" - + "fd5b509050506001610190610f07565b6040518091039082f0801580156101ab573d6000803e3d6000fd" - + "5b5090505060016101b9610f07565b6040518091039082f0801580156101d4573d6000803e3d6000fd5b" - + "5090505060016101e2610f07565b6040518091039082f0801580156101fd573d6000803e3d6000fd5b50" - + "905050600161020b610f07565b6040518091039082f080158015610226573d6000803e3d6000fd5b50905" - + "0506001610234610f07565b6040518091039082f08015801561024f573d6000803e3d6000fd5b5090505" - + "0600161025d610f07565b6040518091039082f080158015610278573d6000803e3d6000fd5b50905050600" - + "1610286610f07565b6040518091039082f0801580156102a1573d6000803e3d6000fd5b509050506001610" - + "2af610f07565b6040518091039082f0801580156102ca573d6000803e3d6000fd5b5090505060016102d" - + "8610f07565b6040518091039082f0801580156102f3573d6000803e3d6000fd5b509050506001610301610" - + "f07565b6040518091039082f08015801561031c573d6000803e3d6000fd5b50905050600161032a610f07" - + "565b6040518091039082f080158015610345573d6000803e3d6000fd5b509050506001610353610f07565b" - + "6040518091039082f08015801561036e573d6000803e3d6000fd5b50905050600161037c610f07565b6040" - + "518091039082f080158015610397573d6000803e3d6000fd5b5090505060016103a5610f07565b60405180" - + "91039082f0801580156103c0573d6000803e3d6000fd5b5090505060016103ce610f07565b604051809103" - + "9082f0801580156103e9573d6000803e3d6000fd5b5090505060016103f7610f07565b604051809103908" - + "2f080158015610412573d6000803e3d6000fd5b509050506001610420610f07565b6040518091039082f0" - + "8015801561043b573d6000803e3d6000fd5b509050506001610449610f07565b6040518091039082f080" - + "158015610464573d6000803e3d6000fd5b509050506001610472610f07565b6040518091039082f08015" - + "801561048d573d6000803e3d6000fd5b50905050600161049b610f07565b6040518091039082f0801580" - + "156104b6573d6000803e3d6000fd5b5090505060016104c4610f07565b6040518091039082f08015801" - + "56104df573d6000803e3d6000fd5b5090505060016104ed610f07565b6040518091039082f080158015" - + "610508573d6000803e3d6000fd5b509050506001610516610f07565b6040518091039082f0801580156" - + "10531573d6000803e3d6000fd5b50905050600161053f610f07565b6040518091039082f0801580156" - + "1055a573d6000803e3d6000fd5b509050506001610568610f07565b6040518091039082f0801580156" - + "10583573d6000803e3d6000fd5b509050506001610591610f07565b6040518091039082f080158015" - + "6105ac573d6000803e3d6000fd5b5090505060016105ba610f07565b6040518091039082f0801580156" - + "105d5573d6000803e3d6000fd5b5090505060016105e3610f07565b6040518091039082f0801580156" - + "105fe573d6000803e3d6000fd5b50905050600161060c610f07565b6040518091039082f0801580156" - + "10627573d6000803e3d6000fd5b509050506001610635610f07565b6040518091039082f0801580156" - + "10650573d6000803e3d6000fd5b50905050600161065e610f07565b6040518091039082f0801580156" - + "10679573d6000803e3d6000fd5b509050506001610687610f07565b6040518091039082f0801580156" - + "106a2573d6000803e3d6000fd5b5090505060016106b0610f07565b6040518091039082f0801580156" - + "106cb573d6000803e3d6000fd5b5090505060016106d9610f07565b6040518091039082f0801580156" - + "106f4573d6000803e3d6000fd5b509050506001610702610f07565b6040518091039082f0801580156" - + "1071d573d6000803e3d6000fd5b50905050600161072b610f07565b6040518091039082f0801580156" - + "10746573d6000803e3d6000fd5b509050506001610754610f07565b6040518091039082f0801580156" - + "1076f573d6000803e3d6000fd5b50905050600161077d610f07565b6040518091039082f0801580156" - + "10798573d6000803e3d6000fd5b5090505060016107a6610f07565b6040518091039082f0801580156" - + "107c1573d6000803e3d6000fd5b5090505060016107cf610f07565b6040518091039082f0801580156" - + "107ea573d6000803e3d6000fd5b5090505060016107f8610f07565b6040518091039082f080158015610813" - + "573d6000803e3d6000fd5b509050506001610821610f07565b6040518091039082f08015801561083c57" - + "3d6000803e3d6000fd5b50905050600161084a610f07565b6040518091039082f080158015610865573d" - + "6000803e3d6000fd5b509050506001610873610f07565b6040518091039082f08015801561088e57" - + "3d6000803e3d6000fd5b50905050600161089c610f07565b6040518091039082f0801580156108b7573" - + "d6000803e3d6000fd5b5090505060016108c5610f07565b6040518091039082f0801580156108e0573d6" - + "000803e3d6000fd5b5090505060016108ee610f07565b6040518091039082f080158015610909573d6000" - + "803e3d6000fd5b509050506001610917610f07565b6040518091039082f080158015610932573d6000803e" - + "3d6000fd5b509050506001610940610f07565b6040518091039082f08015801561095b573d6000803e3d6" - + "000fd5b509050506001610969610f07565b6040518091039082f080158015610984573d6000803e3d6000" - + "fd5b509050506001610992610f07565b6040518091039082f0801580156109ad573d6000803e3d6000fd5" - + "b5090505060016109bb610f07565b6040518091039082f0801580156109d6573d6000803e3d6000fd5b50" - + "90505060016109e4610f07565b6040518091039082f0801580156109ff573d6000803e3d6000fd5b50905" - + "0506001610a0d610f07565b6040518091039082f080158015610a28573d6000803e3d6000fd5b50905050" - + "6001610a36610f07565b6040518091039082f080158015610a51573d6000803e3d6000fd5b50905050600" - + "1610a5f610f07565b6040518091039082f080158015610a7a573d6000803e3d6000fd5b50905050600161" - + "0a88610f07565b6040518091039082f080158015610aa3573d6000803e3d6000fd5b509050506001610ab1" - + "610f07565b6040518091039082f080158015610acc573d6000803e3d6000fd5b509050506001610ada610f" - + "07565b6040518091039082f080158015610af5573d6000803e3d6000fd5b509050506001610b03610f0756" - + "5b6040518091039082f080158015610b1e573d6000803e3d6000fd5b509050506001610b2c610f07565b60" - + "40518091039082f080158015610b47573d6000803e3d6000fd5b509050506001610b55610f07565b60405" - + "18091039082f080158015610b70573d6000803e3d6000fd5b509050506001610b7e610f07565b60405180" - + "91039082f080158015610b99573d6000803e3d6000fd5b509050506001610ba7610f07565b60405180910" - + "39082f080158015610bc2573d6000803e3d6000fd5b509050506001610bd0610f07565b60405180910390" - + "82f080158015610beb573d6000803e3d6000fd5b509050506001610bf9610f07565b6040518091039082f" - + "080158015610c14573d6000803e3d6000fd5b509050506001610c22610f07565b6040518091039082f080" - + "158015610c3d573d6000803e3d6000fd5b509050506001610c4b610f07565b6040518091039082f080158" - + "015610c66573d6000803e3d6000fd5b509050506001610c74610f07565b6040518091039082f080158015" - + "610c8f573d6000803e3d6000fd5b509050506001610c9d610f07565b6040518091039082f080158015610" - + "cb8573d6000803e3d6000fd5b509050506001610cc6610f07565b6040518091039082f080158015610ce1" - + "573d6000803e3d6000fd5b509050506001610cef610f07565b6040518091039082f080158015610d0a573" - + "d6000803e3d6000fd5b509050506001610d18610f07565b6040518091039082f080158015610d33573d60" - + "00803e3d6000fd5b509050506001610d41610f07565b6040518091039082f080158015610d5c573d60008" - + "03e3d6000fd5b509050506001610d6a610f07565b6040518091039082f080158015610d85573d6000803e" - + "3d6000fd5b509050506001610d93610f07565b6040518091039082f080158015610dae573d6000803e3d" - + "6000fd5b509050506001610dbc610f07565b6040518091039082f080158015610dd7573d6000803e3d6" - + "000fd5b509050506001610de5610f07565b6040518091039082f080158015610e00573d6000803e3d60" - + "00fd5b509050506001610e0e610f07565b6040518091039082f080158015610e29573d6000803e3d600" - + "0fd5b509050506001610e37610f07565b6040518091039082f080158015610e52573d6000803e3d600" - + "0fd5b509050506001610e60610f07565b6040518091039082f080158015610e7b573d6000803e3d6" - + "000fd5b509050506001610e89610f07565b6040518091039082f080158015610ea4573d6000803e3d" - + "6000fd5b509050506001610eb2610f07565b6040518091039082f080158015610ecd573d6000803e3d6" - + "000fd5b509050506001610edb610f07565b6040518091039082f080158015610ef6573d6000803e3d60" - + "00fd5b505050565b60005481565b60016100ec5b60405161019080610f1883390190560060806040526" - + "0008055610179806100176000396000f3006080604052600436106100615763ffffffff7c0100000000" - + "00000000000000000000000000000000000000000000000060003504166312065fe081146100635780631d1" - + "537e51461008a57806326121ff0146100bd5780634e70b1dc146100d9575b005b34801561006f57600080" - + "fd5b506100786100ee565b60408051918252519081900360200190f35b34801561009657600080fd5b506" - + "1006173ffffffffffffffffffffffffffffffffffffffff6004351660243515156100f3565b6100c56101" - + "42565b604080519115158252519081900360200190f35b3480156100e557600080fd5b506100786101475" - + "65b303190565b60405173ffffffffffffffffffffffffffffffffffffffff831690600090600190828181" - + "81858883f19350505050158015610132573d6000803e3d6000fd5b50801561013e57600080fd5b5050565" - + "b600190565b600054815600a165627a7a723058203a543f0f4070ac04c72fde5beebab99b4973e08f36a98" - + "c25d7d2eff9d15663cc0029a165627a7a72305820734fa6d717e262da9eb3ab3a17009db666b0b3045ac76" - + "895bbe21ca0d83c41740029"; - String abi = "[{\"constant\":false,\"inputs\":[],\"name\":\"getBalance\",\"outputs\":[" - + "{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"" - + "nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"" - + "transfer2\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"" - + "type\":\"function\"},{\"constant\":true,\"inputs\":[]," - + "\"name\":\"num\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\"" - + ":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false," - + "\"inputs\":[],\"name\":\"transfer\",\"outputs\":[],\"payable\":true,\"" - + "stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"" - + "payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}]"; + String filePath = "src/test/resources/soliditycode/" + + "contractInternalTransaction002test4InternalTransaction010.sol"; + String contractName = "A"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, internalTxsAddress, blockingStubFull); @@ -731,7 +442,7 @@ public void test4InternalTransaction010() { infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); Assert.assertTrue(infoById.get().getResultValue() == 0); int transactionsCount = infoById.get().getInternalTransactionsCount(); - Assert.assertEquals(88, transactionsCount); + Assert.assertEquals(76, transactionsCount); dupInternalTrsansactionHash(infoById.get().getInternalTransactionsList()); for (int i = 0; i < transactionsCount; i++) { @@ -751,7 +462,7 @@ public void test4InternalTransaction010() { infoById1 = PublicMethed.getTransactionInfoById(txid1, blockingStubFull); Assert.assertTrue(infoById1.get().getResultValue() == 1); int transactionsCount1 = infoById1.get().getInternalTransactionsCount(); - Assert.assertEquals(89, transactionsCount1); + Assert.assertEquals(76, transactionsCount1); dupInternalTrsansactionHash(infoById1.get().getInternalTransactionsList()); for (int i = 0; i < transactionsCount1; i++) { @@ -774,71 +485,31 @@ public void test5InternalTransaction012() { blockingStubFull)); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName = "AAContract"; - String code = "6080604052610130806100136000396000f3006080604052600436106100275763ffffffff" - + "60e060020a60003504166363f76a6a8114610029575b005b61002773ffffffffffffffffffffffffff" - + "ffffffffffffff600435811690602435168173ffffffffffffffffffffffffffffffffffffffff1660016" - + "0405180807f746573744e4e2861646472657373290000000000000000000000000000000000815250600f" - + "019050604051809103902060e060020a900490836040518363ffffffff1660e060020a02815260040180" - + "8273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffff" - + "ffff16815260200191505060006040518083038185885af1505050505050505600a165627a7a72305820d" - + "f67b7d3a72bdb94e1e8fbcc3aac5d478700fdf55d585e8e218ed9a9b6637ec30029"; - String abi = "[{\"constant\":false,\"inputs\":[{\"name\":\"bAddr\",\"type\":\"address\"" - + "},{\"name\":\"eAddr\",\"type\":\"address\"}],\"name\":\"test1\",\"outputs\":[]" - + ",\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs" - + "\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}," - + "{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]"; + String filePath = "src/test/resources/soliditycode/" + + "contractInternalTransaction002test5InternalTransaction012.sol"; + String contractName = "A"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, internalTxsAddress, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - - String contractName1 = "BContract"; - String code1 = "60806040526102de806100136000396000f30060806040526004361061004b5763ffffffff7c01" - + "000000000000000000000000000000000000000000000000000000006000350416637c0e37a6811" - + "461004d578063ab5ed1501461006e575b005b61004b73fffffffffffffffffffffffffffffffff" - + "fffffff60043516610088565b610076610180565b60408051918252519081900360200190f35b60006" - + "103e8610095610185565b6040518091039082f0801580156100b0573d6000803e3d6000fd5b50905090" - + "508073ffffffffffffffffffffffffffffffffffffffff1663088a91f5836040518263ffffffff167c010" - + "0000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffff" - + "ffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019" - + "15050602060405180830381600087803b15801561015057600080fd5b505af1158015610164573d600080" - + "3e3d6000fd5b505050506040513d602081101561017a57600080fd5b50505050565b600190565b6040516" - + "1011d80610196833901905600608060405261010a806100136000396000f3006080604052600436106025" - + "5763ffffffff60e060020a600035041663088a91f581146027575b005b604673fffffffffffffffffffff" - + "fffffffffffffffffff600435166058565b60408051918252519081900360200190f35b60008173ffffff" - + "ffffffffffffffffffffffffffffffffff16600160405180807f6765745a65726f2829000000000000000" - + "00000000000000000000000000000008152506009019050604051809103902060e060020a900490604051" - + "8263ffffffff1660e060020a02815260040160006040518083038185885af19350505050509190505600a" - + "165627a7a72305820dd7a7f17b07e2480b36bc7468d984ead013aae68a1eb55dbd5f1ede715affd1e0029" - + "a165627a7a72305820cb8ab1f0fbe80c0c0e76a374dda5663ec870b576de98367035aa7606c07707a00029"; - String abi1 = "[{\"constant\":false,\"inputs\":[{\"name\":\"eAddress\",\"type\":\"address" - + "\"}],\"name\":\"testNN\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"" - + "payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"" - + "getOne\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"" - + "stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\"" - + ":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":" - + "true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]"; + String contractName1 = "B"; + HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); + String code1 = retMap1.get("byteCode").toString(); + String abi1 = retMap1.get("abI").toString(); byte[] contractAddress1 = PublicMethed .deployContract(contractName1, abi1, code1, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, internalTxsAddress, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName2 = "EContract"; - String code2 = "6080604052609f806100126000396000f30060806040526004361060485763ffffffff7" - + "c01000000000000000000000000000000000000000000000000000000006000350416639" - + "f3f89dc8114604a578063fbf004e3146062575b005b60506068565b6040805191825251908190" - + "0360200190f35b6050606d565b600090565b60008080fd00a165627a7a72305820fed1b0b" - + "287ea849db12d31a338942ee575c9e0bbdb07e7da09a4d432511308120029"; - String abi2 = "[{\"constant\":false,\"inputs\":[],\"name\":\"getZero\",\"outputs\":" - + "[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\"" - + ":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name" - + "\":\"newBAndTransfer\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"" - + "payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs" - + "\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}" - + ",{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]"; + String contractName2 = "E"; + HashMap retMap2 = PublicMethed.getBycodeAbi(filePath, contractName2); + String code2 = retMap1.get("byteCode").toString(); + String abi2 = retMap1.get("abI").toString(); byte[] contractAddress2 = PublicMethed .deployContract(contractName2, abi2, code2, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, diff --git a/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction003.java b/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction003.java index a7736e7b646..7cbdd1e786d 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction003.java +++ b/src/test/java/stest/tron/wallet/dailybuild/internaltransaction/ContractInternalTransaction003.java @@ -3,6 +3,7 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Optional; import java.util.concurrent.TimeUnit; @@ -93,59 +94,22 @@ public void testInternalTransaction013() { .sendcoin(internalTxsAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, blockingStubFull)); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName = "AAContract"; - String code = "6080604052610325806100136000396000f3006080604052600436106100325763ffff" - + "ffff60e060020a600035041663a408b1f58114610034578063bc07c44314610055575b005b6100" - + "3273ffffffffffffffffffffffffffffffffffffffff60043516610079565b61003273ffffffffff" - + "ffffffffffffffffffffffffffffff60043516602435610138565b6000600a6100856101b9565b60405180" - + "91039082f0801580156100a0573d6000803e3d6000fd5b50604080517f550082770000000000000000000" - + "0000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86" - + "811660048301526002602483015291519294509084169250635500827791604480830192600092919082" - + "900301818387803b15801561011c57600080fd5b505af1158015610130573d6000803e3d6000fd5b5050" - + "50505050565b8173ffffffffffffffffffffffffffffffffffffffff168160405180807f6e657742416e" - + "645472616e73666572282900000000000000000000000000000081525060110190506040518091039020" - + "60e060020a9004906040518263ffffffff1660e060020a02815260040160006040518083038185885af150" - + "505050505050565b604051610130806101ca833901905600608060405261011d806100136000396000f300" - + "608060405260043610602f5763ffffffff60e060020a6000350416635500827781146031578063ab5ed150" - + "146053575b005b602f73ffffffffffffffffffffffffffffffffffffffff60043516602435606b565b6" - + "05960ec565b60408051918252519081900360200190f35b8173fffffffffffffffffffffffffffff" - + "fffffffffff168160405180807f6765744f6e652829000000000000000000000000000000000000000000" - + "0000008152506008019050604051809103902060e060020a9004906040518263ffffffff1660e060020a0" - + "2815260040160006040518083038185885af150505050505050565b6001905600a165627a7a72305820c8" - + "0c862e9b92c99081d883a4a9650bdc89261492444344cce90ce1aca0aca7b50029a165627a7a72305820e" - + "3df1a66607d98852c9fa349b7187157683ed7c338501b89cc7c432a4ecb4b180029"; - String abi = "[{\"constant\":false,\"inputs\":[{\"name\":\"dAddr\",\"type\":\"address\"}]," - + "\"name\":\"test1\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\"," - + "\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"cAddress\",\"type" - + "\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"test2\",\"" - + "outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"}," - + "{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"" - + "constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"" - + "fallback\"}]"; + String filePath = "src/test/resources/soliditycode/" + + "contractInternalTransaction003testInternalTransaction013.sol"; + String contractName = "A"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, internalTxsAddress, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName1 = "DContract"; - String code1 = "6080604052610172806100136000396000f300608060405260043610603e5763ffffffff7c0" - + "100000000000000000000000000000000000000000000000000000000600035041663ab5ed150811460" - + "40575b005b60466058565b60408051918252519081900360200190f35b600080600560636086565b60" - + "40518091039082f080158015607d573d6000803e3d6000fd5b50905090505090565b60405160b18061" - + "00968339019056006080604052609f806100126000396000f30060806040526004361060485763fffff" - + "fff7c01000000000000000000000000000000000000000000000000000000006000350416639f3f89dc81" - + "14604a578063fbf004e3146062575b005b60506068565b60408051918252519081900360200190f35b60" - + "50606d565b600090565b60008080fd00a165627a7a7230582000d806a1f2f66196834b9dcd54c041736" - + "7166141e926631aba02ebd6605677120029a165627a7a723058202cd1dc37e6bc871aa8edd9fb2" - + "1f8f81e56daccd6e2c48ddd5e65ba42d230a94d0029"; - String abi1 = "[{\"constant\":false,\"inputs\":[{\"name\":\"eAddress\",\"type\":\"address\"}]" - + ",\"name\":\"testNN\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\"" - + ",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"getOne\",\"" - + "outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability" - + "\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"" - + "stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"" - + "stateMutability\":\"payable\",\"type\":\"fallback\"}]"; + String contractName1 = "D"; + HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); + String code1 = retMap1.get("byteCode").toString(); + String abi1 = retMap1.get("abI").toString(); byte[] contractAddress1 = PublicMethed .deployContract(contractName1, abi1, code1, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, @@ -198,84 +162,32 @@ public void testInternalTransaction014() { .sendcoin(internalTxsAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, blockingStubFull)); PublicMethed.waitProduceNextBlock(blockingStubFull); - - String contractName = "AAContract"; - String code = "6080604052610264806100136000396000f30060806040526004361061003d5763fffffff" - + "f60e060020a600035041663648efe8b811461003f578063b45f578b14610059578063d81845211461" - + "0073575b005b61003d600160a060020a036004358116906024351661008d565b61003d600160a06002" - + "0a036004358116906024351661011c565b61003d600160a060020a03600435811690602435166101a956" - + "5b81600160a060020a031660405180807f7472616e73666572546f2861646472657373290000000000000" - + "00000000000008152506013019050604051809103902060e060020a9004826040518263ffffffff1660e0" - + "60020a0281526004018082600160a060020a0316600160a060020a03168152602001915050600060405180" - + "8303816000875af2505050505050565b81600160a060020a031660405180807f7472616e73666572546f28" - + "6164647265737329000000000000000000000000008152506013019050604051809103902060e060020a9" - + "004826040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03" - + "168152602001915050600060405180830381865af4505050505050565b81600160a060020a0316604051" - + "80807f7472616e73666572546f28616464726573732900000000000000000000000000815250601301905" - + "0604051809103902060e060020a9004826040518263ffffffff1660e060020a0281526004018082600160" - + "a060020a0316600160a060020a031681526020019150506000604051808303816000875af1505050505050" - + "5600a165627a7a72305820bd42fc60a3c727816805f1f50ff60dd6196a8460b042f1cde38f905121aed" - + "bca0029"; - String abi = "[{\"constant\":false,\"inputs\":[{\"name\":\"called_address\",\"type\":" - + "\"address\"},{\"name\":\"c\",\"type\":\"address\"}],\"name\":\"sendToB3\",\"" - + "outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"" - + "},{\"constant\":false,\"inputs\":[{\"name\":\"called_address\",\"type\":\"address\"" - + "},{\"name\":\"c\",\"type\":\"address\"}],\"name\":\"sendToB\",\"outputs\":[],\"" - + "payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant" - + "\":false,\"inputs\":[{\"name\":\"called_address\",\"type\":\"address\"},{\"name\"" - + ":\"c\",\"type\":\"address\"}],\"name\":\"sendToB2\",\"outputs\":[],\"payable\":true" - + ",\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":" - + "true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"" - + "stateMutability\":\"payable\",\"type\":\"fallback\"}]"; + String filePath = "src/test/resources/soliditycode/" + + "contractInternalTransaction003testInternalTransaction014.sol"; + String contractName = "callerContract"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, internalTxsAddress, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName1 = "BContract"; - String code1 = "6080604052610166806100136000396000f3006080604052600436106100325763ffffffff" - + "60e060020a6000350416630223024e8114610034578063a03fa7e314610055575b005b61003273fff" - + "fffffffffffffffffffffffffffffffffffff60043516610076565b61003273ffffffffffffffffffff" - + "ffffffffffffffffffff600435166100f7565b8073ffffffffffffffffffffffffffffffffffffffff166" - + "00560405180807f7365744928290000000000000000000000000000000000000000000000000000815250" - + "6006019050604051809103902060e060020a9004906040518263ffffffff1660e060020a02815260040160" - + "006040518083038185885af1505050505050565b60405173fffffffffffffffffffffffffffffffffff" - + "fffff82169060009060059082818181858883f19350505050158015610136573d6000803e3d6000fd5b5" - + "0505600a165627a7a72305820c2a310e325ce519d5d9b53498794e528854379d82b5e931712" - + "b86f034ede63dd0029"; - String abi1 = "[{\"constant\":false,\"inputs\":[{\"name\":\"c\",\"type\":\"address\"}]" - + ",\"name\":\"setIinC\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"" - + "payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"" - + "toAddress\",\"type\":\"address\"}],\"name\":\"transferTo\",\"outputs\":[],\"" - + "payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs" - + "\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}" - + ",{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]"; + String contractName1 = "calledContract"; + HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); + String code1 = retMap1.get("byteCode").toString(); + String abi1 = retMap1.get("abI").toString(); byte[] contractAddress1 = PublicMethed .deployContract(contractName1, abi1, code1, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, internalTxsAddress, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName2 = "CContract"; - String code2 = "6080604052610166806100136000396000f3006080604052600436106100325763fffffff" - + "f60e060020a6000350416630223024e8114610034578063a03fa7e314610055575b005b61003273fff" - + "fffffffffffffffffffffffffffffffffffff60043516610076565b61003273ffffffffffffffffffff" - + "ffffffffffffffffffff600435166100f7565b8073ffffffffffffffffffffffffffffffffffffffff16" - + "600560405180807f736574492829000000000000000000000000000000000000000000000000000081" - + "52506006019050604051809103902060e060020a9004906040518263ffffffff1660e060020a028152" - + "60040160006040518083038185885af1505050505050565b60405173ffffffffffffffffffffffffffff" - + "ffffffffffff82169060009060059082818181858883f19350505050158015610136573d6000803e3d600" - + "0fd5b50505600a165627a7a72305820c2a310e325ce519d5d9b53498794e528854379d82b5e93" - + "1712b86f034ede63dd0029"; - - String abi2 = "[{\"constant\":false,\"inputs\":[{\"name\":\"c\",\"type\":\"address\"}" - + "],\"name\":\"setIinC\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"" - + "payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"" - + "toAddress\",\"type\":\"address\"}],\"name\":\"transferTo\",\"outputs\":[],\"" - + "payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs" - + "\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}" - + ",{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]"; + String contractName2 = "c"; + HashMap retMap2 = PublicMethed.getBycodeAbi(filePath, contractName2); + String code2 = retMap2.get("byteCode").toString(); + String abi2 = retMap2.get("abI").toString(); byte[] contractAddress2 = PublicMethed .deployContract(contractName2, abi2, code2, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, @@ -381,89 +293,31 @@ public void testInternalTransaction015() { .sendcoin(internalTxsAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, blockingStubFull)); PublicMethed.waitProduceNextBlock(blockingStubFull); + String filePath = "src/test/resources/soliditycode/" + + "contractInternalTransaction003testInternalTransaction015.sol"; + String contractName = "A"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); - String contractName = "AAContract"; - String code = "608060405261037c806100136000396000f3006080604052600436106100325763fff" - + "fffff60e060020a60003504166363f76a6a8114610034578063bc07c4431461005b575" - + "b005b61003273ffffffffffffffffffffffffffffffffffffffff600435811690602435166" - + "1007f565b61003273ffffffffffffffffffffffffffffffffffffffff6004351660243561014756" - + "5b6000600a61008b6101c8565b6040518091039082f0801580156100a6573d6000803e3d6000fd5b50" - + "604080517f678d55d700000000000000000000000000000000000000000000000000000000815273fff" - + "fffffffffffffffffffffffffffffffffffff87811660048301526002602483015286811660448301529" - + "151929450908416925063678d55d791606480830192600092919082900301818387803b15801561012a57" - + "600080fd5b505af115801561013e573d6000803e3d6000fd5b50505050505050565b8173ffffffffffffff" - + "ffffffffffffffffffffffffff168160405180807f6e657742416e645472616e7366657228290000000000" - + "000000000000000000008152506011019050604051809103902060e060020a9004906040518263ffffffff" - + "1660e060020a02815260040160006040518083038185885af150505050505050565b604051610178806101" - + "d98339019056006080604052610165806100136000396000f30060806040526004361061004b5763ffffff" - + "ff7c0100000000000000000000000000000000000000000000000000000000600035041663678d55d781146" - + "1004d578063ab5ed15014610078575b005b61004b73ffffffffffffffffffffffffffffffffffffffff6004" - + "358116906024359060443516610092565b610080610134565b60408051918252519081900360200190f35" - + "b604080517f6765744f6e652861646472657373290000000000000000000000000000000000815281519" - + "0819003600f01812063ffffffff7c0100000000000000000000000000000000000000000000000000000" - + "000918290049081169091028252306004830152915173ffffffffffffffffffffffffffffffffffffffff" - + "8616929185916024808301926000929190829003018185885af15050505050505050565b60019056" - + "00a165627a7a72305820bf4026737c4ded60e6c012338670a169e8f54a6b95e4203f58d5a8c7657bcd7" - + "00029a165627a7a7230582094c3b4926d5e387c21ed19842b73e765aa153dc93e0753c0ec10b87ce26e" - + "fafb0029"; - String abi = "[{\"constant\":false,\"inputs\":[{\"name\":\"dAddr\",\"type\":\"address\"}," - + "{\"name\":\"eAddr\",\"type\":\"address\"}],\"name\":\"test1\",\"outputs\":[],\"" - + "payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant" - + "\":false,\"inputs\":[{\"name\":\"cAddress\",\"type\":\"address\"},{\"name\":\"amount" - + "\",\"type\":\"uint256\"}],\"name\":\"test2\",\"outputs\":[],\"payable\":true,\"" - + "stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\"" - + ":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true" - + ",\"stateMutability\":\"payable\",\"type\":\"fallback\"}]"; contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, internalTxsAddress, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - - String contractName1 = "DContract"; - String code1 = "608060405261026f806100136000396000f3006080604052600436106100405763ffffffff7c" - + "0100000000000000000000000000000000000000000000000000000000600035041663088a91f5" - + "8114610042575b005b61004073ffffffffffffffffffffffffffffffffffffffff600435166000" - + "600561006a610141565b6040518091039082f080158015610085573d6000803e3d6000fd5b509" - + "05090508073ffffffffffffffffffffffffffffffffffffffff1663dbc1f226836040518263ff" - + "ffffff167c01000000000000000000000000000000000000000000000000000000000281526004" - + "01808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffff" - + "ffffffffffffff168152602001915050600060405180830381600087803b1580156101255760008" - + "0fd5b505af1158015610139573d6000803e3d6000fd5b505050505050565b60405160f380610151" - + "833901905600608060405260e1806100126000396000f30060806040526004361060525763ffffff" - + "ff7c01000000000000000000000000000000000000000000000000000000006000350416639f3f89" - + "dc81146054578063dbc1f22614606c578063fbf004e314608b575b005b605a6091565b6040805191" - + "8252519081900360200190f35b605273ffffffffffffffffffffffffffffffffffffffff600435166" - + "096565b605a60af565b600090565b8073ffffffffffffffffffffffffffffffffffffffff16ff5b60" - + "008080fd00a165627a7a72305820389aafc091c92d0770f25d3a3ffb9134b658464f089aec67b6dee" - + "967f44067ab0029a165627a7a72305820074530d5e3beecdd1300266aa5e740befa1c65630aebd0a6" - + "2f6d3dba862192dd0029"; - String abi1 = "[{\"constant\":false,\"inputs\":[{\"name\":\"eAddress\",\"type\":\"" - + "address\"}],\"name\":\"getOne\",\"outputs\":[],\"payable\":true,\"stateMutability" - + "\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"" - + "stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true," - + "\"stateMutability\":\"payable\",\"type\":\"fallback\"}]"; + String contractName1 = "D"; + HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); + String code1 = retMap1.get("byteCode").toString(); + String abi1 = retMap1.get("abI").toString(); byte[] contractAddress1 = PublicMethed .deployContract(contractName1, abi1, code1, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, internalTxsAddress, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName2 = "EContract"; - String code2 = "608060405260e1806100126000396000f30060806040526004361060525763ffffffff7c0" - + "1000000000000000000000000000000000000000000000000000000006000350416639f3f89dc811460" - + "54578063dbc1f22614606c578063fbf004e314608b575b005b605a6091565b60408051918252519081" - + "900360200190f35b605273ffffffffffffffffffffffffffffffffffffffff600435166096565" - + "b605a60af565b600090565b8073ffffffffffffffffffffffffffffffffffffffff16ff5b60008080fd00a" - + "165627a7a72305820389aafc091c92d0770f25d3a3ffb9134b658464f089aec67b6dee967f44067ab0029"; - String abi2 = "[{\"constant\":false,\"inputs\":[],\"name\":\"getZero\",\"outputs\":[{\"name" - + "\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type" - + "\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"" - + "address\"}],\"name\":\"suicide\",\"outputs\":[],\"payable\":true,\"stateMutability\"" - + ":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"" - + "newBAndTransfer\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\"" - + ":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"" - + "payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"" - + "payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"}]"; + String contractName2 = "E"; + HashMap retMap2 = PublicMethed.getBycodeAbi(filePath, contractName2); + String code2 = retMap2.get("byteCode").toString(); + String abi2 = retMap2.get("abI").toString(); byte[] contractAddress2 = PublicMethed .deployContract(contractName2, abi2, code2, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, @@ -495,118 +349,12 @@ public void testInternalTransaction016() { .sendcoin(internalTxsAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, blockingStubFull)); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName = "AAContract"; - String code = "608060405260008055611033806100176000396000f300608060405260043610610061576" - + "3ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041" - + "66312065fe08114610066578063248c44e81461008d5780634e70b1dc146100975780638a4068dd14" - + "6100ac575b600080fd5b34801561007257600080fd5b5061007b6100b4565b604080519182525190819" - + "00360200190f35b6100956100b9565b005b3480156100a357600080fd5b5061007b610e14565b610095" - + "610e1a565b303190565b600060016100c5610e22565b6040518091039082f0801580156100e0573d6000" - + "803e3d6000fd5b5090505060016100ee610e22565b6040518091039082f080158015610109573d6000803" - + "e3d6000fd5b509050506001610117610e22565b6040518091039082f080158015610132573d6000803e3d6" - + "000fd5b509050506001610140610e22565b6040518091039082f08015801561015b573d6000803e3d6000" - + "fd5b509050506001610169610e22565b6040518091039082f080158015610184573d6000803e3d6000" - + "fd5b509050506001610192610e22565b6040518091039082f0801580156101ad573d6000803e3d6000f" - + "d5b5090505060016101bb610e22565b6040518091039082f0801580156101d6573d6000803e3d6000fd5" - + "b5090505060016101e4610e22565b6040518091039082f0801580156101ff573d6000803e3d6000fd5b5" - + "0905050600161020d610e22565b6040518091039082f080158015610228573d6000803e3d6000fd5b509" - + "050506001610236610e22565b6040518091039082f080158015610251573d6000803e3d6000fd5b509050" - + "50600161025f610e22565b6040518091039082f08015801561027a573d6000803e3d6000fd5b509050506" - + "001610288610e22565b6040518091039082f0801580156102a3573d6000803e3d6000fd5b509050506001" - + "6102b1610e22565b6040518091039082f0801580156102cc573d6000803e3d6000fd5b5090505060016102" - + "da610e22565b6040518091039082f0801580156102f5573d6000803e3d6000fd5b50905050600161030361" - + "0e22565b6040518091039082f08015801561031e573d6000803e3d6000fd5b50905050600161032c610e22" - + "565b6040518091039082f080158015610347573d6000803e3d6000fd5b509050506001610355610e22565" - + "b6040518091039082f080158015610370573d6000803e3d6000fd5b50905050600161037e610e22565b6" - + "040518091039082f080158015610399573d6000803e3d6000fd5b5090505060016103a7610e22565b604" - + "0518091039082f0801580156103c2573d6000803e3d6000fd5b5090505060016103d061" - + "0e22565b6040518091039082f0801580156103eb573d6000803e3d6000fd5b50905050600" - + "16103f9610e22565b6040518091039082f080158015610414573d6000803e3d6000fd5b509050506" - + "001610422610e22565b6040518091039082f08015801561043d573d6000803e3d6000fd5b509050506" - + "00161044b610e22565b6040518091039082f080158015610466573d6000803e3d6000fd5b50905050" - + "6001610474610e22565b6040518091039082f08015801561048f573d6000803e3d6000fd5b509050506" - + "00161049d610e22565b6040518091039082f0801580156104b8573d6000803e3d6000fd5b5090505060016" - + "104c6610e22565b6040518091039082f0801580156104e1573d6000803e3d6000fd5b50905050600161" - + "04ef610e22565b6040518091039082f08015801561050a573d6000803e3d6000fd5b509050506001610" - + "518610e22565b6040518091039082f080158015610533573d6000803e3d6000fd5b5090505060016105" - + "41610e22565b6040518091039082f08015801561055c573d6000803e3d6000fd5b50905050600161056a" - + "610e22565b6040518091039082f080158015610585573d6000803e3d6000fd5b50905050600161059361" - + "0e22565b6040518091039082f0801580156105ae573d6000803e3d6000fd5b5090505060016105bc610e" - + "22565b6040518091039082f0801580156105d7573d6000803e3d6000fd5b5090505060016105e5610e22" - + "565b6040518091039082f080158015610600573d6000803e3d6000fd5b50905050600161060e610e2256" - + "5b6040518091039082f080158015610629573d6000803e3d6000fd5b509050506001610637610e22565b" - + "6040518091039082f080158015610652573d6000803e3d6000fd5b509050506001610660610e22565b60" - + "40518091039082f08015801561067b573d6000803e3d6000fd5b509050506001610689610e22565b6040" - + "518091039082f0801580156106a4573d6000803e3d6000fd5b5090505060016106b2610e22565b6" - + "040518091039082f0801580156106cd573d6000803e3d6000fd5b5090505060016106db610e22565b" - + "6040518091039082f0801580156106f6573d6000803e3d6000fd5b509050506001610704610e22565b" - + "6040518091039082f08015801561071f573d6000803e3d6000fd5b50905050600161072d610e22565b6" - + "040518091039082f080158015610748573d6000803e3d6000fd5b509050506001610756610e22565b60" - + "40518091039082f080158015610771573d6000803e3d6000fd5b50905050600161077f610e22565b6040" - + "518091039082f08015801561079a573d6000803e3d6000fd5b5090505060016107a8610e22565b604051" - + "8091039082f0801580156107c3573d6000803e3d6000fd5b5090505060016107d1610e22565b60405180" - + "91039082f0801580156107ec573d6000803e3d6000fd5b5090505060016107fa610e22565b6040518091" - + "039082f080158015610815573d6000803e3d6000fd5b509050506001610823610e22565b6040518091039" - + "082f08015801561083e573d6000803e3d6000fd5b50905050600161084c610e22565b6040518091039082" - + "f080158015610867573d6000803e3d6000fd5b509050506001610875610e22565b6040518091039082f08" - + "0158015610890573d6000803e3d6000fd5b50905050600161089e610e22565b6040518091039082f08015" - + "80156108b9573d6000803e3d6000fd5b5090505060016108c7610e22565b6040518091039082f080158015" - + "6108e2573d6000803e3d6000fd5b5090505060016108f0610e22565b6040518091039082f0801580156109" - + "0b573d6000803e3d6000fd5b509050506001610919610e22565b6040518091039082f08015801561093457" - + "3d6000803e3d6000fd5b509050506001610942610e22565b6040518091039082f08015801561095d573d60" - + "00803e3d6000fd5b50905050600161096b610e22565b6040518091039082f080158015610986573d6000803" - + "e3d6000fd5b509050506001610994610e22565b6040518091039082f0801580156109af573d6000803e3d60" - + "00fd5b5090505060016109bd610e22565b6040518091039082f0801580156109d8573d6000803e3d6000fd5" - + "b5090505060016109e6610e22565b6040518091039082f080158015610a01573d6000803e3d6000fd5b5090" - + "50506001610a0f610e22565b6040518091039082f080158015610a2a573d6000803e3d6000fd5b509050506" - + "001610a38610e22565b6040518091039082f080158015610a53573d6000803e3d6000fd5b50905050600161" - + "0a61610e22565b6040518091039082f080158015610a7c573d6000803e3d6000fd5b509050506001610a8a6" - + "10e22565b6040518091039082f080158015610aa5573d6000803e3d6000fd5b509050506001610ab3610e22" - + "565b6040518091039082f080158015610ace573d6000803e3d6000fd5b509050506001610adc610e225" - + "65b6040518091039082f080158015610af7573d6000803e3d6000fd5b509050506001610b05610e2256" - + "5b6040518091039082f080158015610b20573d6000803e3d6000fd5b509050506001610b2e610e2256" - + "5b6040518091039082f080158015610b49573d6000803e3d6000fd5b509050506001610b57610e2256" - + "5b6040518091039082f080158015610b72573d6000803e3d6000fd5b509050506001610b80610e22565b" - + "6040518091039082f080158015610b9b573d6000803e3d6000fd5b509050506001610ba9610e22565b6" - + "040518091039082f080158015610bc4573d6000803e3d6000fd5b509050506001610bd2610e22565b60" - + "40518091039082f080158015610bed573d6000803e3d6000fd5b509050506001610bfb610e22565b604" - + "0518091039082f080158015610c16573d6000803e3d6000fd5b509050506001610c24610e22565b60405" - + "18091039082f080158015610c3f573d6000803e3d6000fd5b509050506001610c4d610e22565b6040518" - + "091039082f080158015610c68573d6000803e3d6000fd5b509050506001610c76610e22565b60405180" - + "91039082f080158015610c91573d6000803e3d6000fd5b509050506001610c9f610e22565b6040518091" - + "039082f080158015610cba573d6000803e3d6000fd5b509050506001610cc8610e22565b604051809103" - + "9082f080158015610ce3573d6000803e3d6000fd5b509050506001610cf1610e22565b604051809103908" - + "2f080158015610d0c573d6000803e3d6000fd5b509050506001610d1a610e22565b6040518091039082f08" - + "0158015610d35573d6000803e3d6000fd5b509050506001610d43610e22565b6040518091039082f08015" - + "8015610d5e573d6000803e3d6000fd5b509050506001610d6c610e22565b6040518091039082f0801580" - + "15610d87573d6000803e3d6000fd5b50604080517fdbc1f2260000000000000000000000000000000000" - + "00000000000000000000008152306004820152905191935073ffffffffffffffffffffffffffffffffff" - + "ffffff8416925063dbc1f22691602480830192600092919082900301818387803b158015610df9576000" - + "80fd5b505af1158015610e0d573d6000803e3d6000fd5b5050505050565b60005481565b600060016100" - + "ee5b6040516101d580610e338339019056006080604052600080556101be806100176000396000f30" - + "06080604052" - + "6004361061006c5763ffffffff7c01000000000000000000000000000000000000000000000000000000006" - + "0003504166312065fe0811461006e5780631d1537e5146100955780632612" - + "1ff0146100c85780634e70b1dc146100e4578063dbc1f226146100f9575b005b34801561007a5" - + "7600080fd5b5061008361011a565b60408051918252519081900360200190f35b3480156100a15760" - + "0080fd5b5061006c73ffffffffffffffffffffffffffffffffffffffff60043516602435151561011f" - + "565b6100d061016e565b604080519115158252519081900360200190f35b3480156100f057600080fd" - + "5b50610083610173565b61006c73ffffffffffffffffffffffffffffffffffffffff60043516610179" - + "565b303190565b60405173ffffffffffffffffffffffffffffffffffffffff831690600090600190828" - + "18181858883f1935050505015801561015e573d6000803e3d6000fd5b50801561016a57600080fd5b5050" - + "565b600190565b60005481565b8073ffffffffffffffffffffffffffffffffffffffff16ff00a165627a7" - + "a723058200f74b38a39d1c598f23a248095518456f6afe10002bc05919ee73665cf63f3810029a165627a" - + "7a72305820cd622ed71bf5a9328a042c67a5d27ef83c53f390f83e5f337e8c6df32158fa900029"; - String abi = "[{\"constant\":false,\"inputs\":[],\"name\":\"getBalance\",\"outputs\":[{\"name" - + "\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"" - + "type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"transfer2\",\"" - + "outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function" - + "\"},{\"constant\":true,\"inputs\":[],\"name\":\"num\",\"outputs\":[{\"name\":\"\"" - + ",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":" - + "\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"transfer\",\"outputs\"" - + ":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"" - + "inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"constructor" - + "\"}]"; + String filePath = "src/test/resources/soliditycode/" + + "contractInternalTransaction003testInternalTransaction016.sol"; + String contractName = "A"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, internalTxsAddress, blockingStubFull); @@ -621,18 +369,18 @@ public void testInternalTransaction016() { infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); Assert.assertTrue(infoById.get().getResultValue() == 0); int transactionsCount = infoById.get().getInternalTransactionsCount(); - Assert.assertEquals(81, transactionsCount); + Assert.assertEquals(69, transactionsCount); for (int i = 0; i < transactionsCount; i++) { Assert.assertFalse(infoById.get().getInternalTransactions(i).getRejected()); } Assert.assertEquals("suicide", ByteArray - .toStr(infoById.get().getInternalTransactions(80).getNote().toByteArray())); + .toStr(infoById.get().getInternalTransactions(68).getNote().toByteArray())); Assert.assertEquals("call", ByteArray - .toStr(infoById.get().getInternalTransactions(79).getNote().toByteArray())); + .toStr(infoById.get().getInternalTransactions(67).getNote().toByteArray())); Assert.assertEquals(0, - infoById.get().getInternalTransactions(79).getCallValueInfo(0).getCallValue()); + infoById.get().getInternalTransactions(67).getCallValueInfo(0).getCallValue()); Assert.assertEquals(1, - infoById.get().getInternalTransactions(80).getCallValueInfo(0).getCallValue()); + infoById.get().getInternalTransactions(68).getCallValueInfo(0).getCallValue()); for (int i = 0; i < transactionsCount - 2; i++) { Assert.assertEquals("create", ByteArray .toStr(infoById.get().getInternalTransactions(i).getNote().toByteArray())); @@ -649,11 +397,11 @@ public void testInternalTransaction016() { infoById1 = PublicMethed.getTransactionInfoById(txid1, blockingStubFull); int transactionsCount1 = infoById1.get().getInternalTransactionsCount(); - Assert.assertEquals(79, transactionsCount1); + Assert.assertEquals(68, transactionsCount1); for (int i = 0; i < transactionsCount1; i++) { Assert.assertTrue(infoById1.get().getInternalTransactions(i).getRejected()); Assert.assertEquals("create", ByteArray - .toStr(infoById.get().getInternalTransactions(i).getNote().toByteArray())); + .toStr(infoById1.get().getInternalTransactions(i).getNote().toByteArray())); } dupInternalTrsansactionHash(infoById.get().getInternalTransactionsList()); @@ -667,208 +415,12 @@ public void testInternalTransaction017() { .sendcoin(internalTxsAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, blockingStubFull)); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName = "AAContract"; - String code = "608060405260008055611f19806100176000396000f30060806040526004361061006157" - + "63ffffffff7c01000000000000000000000000000000000000000000000000000000006000350" - + "4166312065fe081146100665780631a6952301461008d578063248c44e8146100b05780634e70" - + "b1dc146100b8575b600080fd5b34801561007257600080fd5b5061007b6100cd565b60408051" - + "918252519081900360200190f35b6100ae73fffffffffffffffffffffffffffffffffffffff" - + "f600435166100d2565b005b6100ae610f05565b3480156100c457600080fd5b5061007b611d4" - + "7565b303190565b600060016100de611d4d565b6040518091039082f0801580156100f9573d6000803e" - + "3d6000fd5b509050506001610107611d4d565b6040518091039082f080158015610122573d6000803e3d6" - + "000fd5b509050506001610130611d4d565b6040518091039082f08015801561014b573d6000803e3d6000" - + "fd5b509050506001610159611d4d565b6040518091039082f080158015610174573d6000803e3d6000fd5b5" - + "09050506001610182611d4d565b6040518091039082f08015801561019d573d6000803e3d6000fd5b50905" - + "05060016101ab611d4d565b6040518091039082f0801580156101c6573d6000803e3d6000fd5b5090505" - + "060016101d4611d4d565b6040518091039082f0801580156101ef573d6000803e3d6000fd5b509050506" - + "0016101fd611d4d565b6040518091039082f080158015610218573d6000803e3d6000fd5b50905050600" - + "1610226611d4d565b6040518091039082f080158015610241573d6000803e3d6000fd5b5090505060016" - + "1024f611d4d565b6040518091039082f08015801561026a573d6000803e3d6000fd5b5090505060016102" - + "78611d4d565b6040518091039082f080158015610293573d6000803e3d6000fd5b5090505060016102a16" - + "11d4d565b6040518091039082f0801580156102bc573d6000803e3d6000fd5b5090505060016102ca611d" - + "4d565b6040518091039082f0801580156102e5573d6000803e3d6000fd5b5090505060016102f3611d4d5" - + "65b6040518091039082f08015801561030e573d6000803e3d6000fd5b50905050600161031c611d4d565b60" - + "40518091039082f080158015610337573d6000803e3d6000fd5b509050506001610345611d4d565b604051" - + "8091039082f080158015610360573d6000803e3d6000fd5b50905050600161036e611d4d565b60405180" - + "91039082f080158015610389573d6000803e3d6000fd5b509050506001610397611d4d565b604051809103" - + "9082f0801580156103b2573d6000803e3d6000fd5b5090505060016103c0611d4d565b6040518091039082" - + "f0801580156103db573d6000803e3d6000fd5b5090505060016103e9611d4d565b6040518091039082f0801" - + "58015610404573d6000803e3d6000fd5b509050506001610412611d4d565b6040518091039082f08015801" - + "561042d573d6000803e3d6000fd5b50905050600161043b611d4d565b6040518091039082f080158015610" - + "456573d6000803e3d6000fd5b509050506001610464611d4d565b6040518091039082f08015801561047f5" - + "73d6000803e3d6000fd5b50905050600161048d611d4d565b6040518091039082f0801580156104a8573d6" - + "000803e3d6000fd5b5090505060016104b6611d4d565b6040518091039082f0801580156104d1573d60008" - + "03e3d6000fd5b5090505060016104df611d4d565b6040518091039082f0801580156104fa573d6000803e3" - + "d6000fd5b509050506001610508611d4d565b6040518091039082f080158015610523573d6000803e3d600" - + "0fd5b509050506001610531611d4d565b6040518091039082f08015801561054c573d6000803e3d6000fd5" - + "b50905050600161055a611d4d565b6040518091039082f080158015610575573d6000803e3d6000fd5b509" - + "050506001610583611d4d565b6040518091039082f08015801561059e573d6000803e3d6000fd5b5090505" - + "060016105ac611d4d565b6040518091039082f0801580156105c7573d6000803e3d6000fd5b509050506" - + "0016105d5611d4d565b6040518091039082f0801580156105f0573d6000803e3d6000fd5b50905050600" - + "16105fe611d4d565b6040518091039082f080158015610619573d6000803e3d6000fd5b50905050600161" - + "0627611d4d565b6040518091039082f080158015610642573d6000803e3d6000fd5b509050506001610650" - + "611d4d565b6040518091039082f08015801561066b573d6000803e3d6000fd5b509050506001610679611d" - + "4d565b6040518091039082f080158015610694573d6000803e3d6000fd5b5090505060016106a2611d4" - + "d565b6040518091039082f0801580156106bd573d6000803e3d6000fd5b5090505060016106cb611d4d" - + "565b6040518091039082f0801580156106e6573d6000803e3d6000fd5b5090505060016106f4611d4d5" - + "65b6040518091039082f08015801561070f573d6000803e3d6000fd5b50905050600161071d611d4d5" - + "65b6040518091039082f080158015610738573d6000803e3d6000fd5b509050506001610746611d4d5" - + "65b6040518091039082f080158015610761573d6000803e3d6000fd5b50905050600161076f611d4d5" - + "65b6040518091039082f08015801561078a573d6000803e3d6000fd5b509050506001610798611d4d56" - + "5b6040518091039082f0801580156107b3573d6000803e3d6000fd5b5090505060016107c1611d4d565b6" - + "040518091039082f0801580156107dc573d6000803e3d6000fd5b5090505060016107ea611d4d565b6040" - + "518091039082f080158015610805573d6000803e3d6000fd5b509050506001610813611d4d565b6040518" - + "091039082f08015801561082e573d6000803e3d6000fd5b50905050600161083c611d4d565b6040518091" - + "039082f080158015610857573d6000803e3d6000fd5b509050506001610865611d4d565b6040518091039" - + "082f080158015610880573d6000803e3d6000fd5b50905050600161088e611d4d565b6040518091039082" - + "f0801580156108a9573d6000803e3d6000fd5b5090505060016108b7611d4d565b6040518091039082f08" - + "01580156108d2573d6000803e3d6000fd5b5090505060016108e0611d4d565b6040518091039082f080158" - + "0156108fb573d6000803e3d6000fd5b509050506001610909611d4d565b6040518091039082f080158015" - + "610924573d6000803e3d6000fd5b509050506001610932611d4d565b6040518091039082f080158015610" - + "94d573d6000803e3d6000fd5b50905050600161095b611d4d565b6040518091039082f080158015610976" - + "573d6000803e3d6000fd5b509050506001610984611d4d565b6040518091039082f08015801561099f573" - + "d6000803e3d6000fd5b5090505060016109ad611d4d565b6040518091039082f0801580156109c8573d60" - + "00803e3d6000fd5b5090505060016109d6611d4d565b6040518091039082f0801580156109f1573d60008" - + "03e3d6000fd5b5090505060016109ff611d4d565b6040518091039082f080158015610a1a573d6000803e" - + "3d6000fd5b509050506001610a28611d4d565b6040518091039082f080158015610a43573d6000803e" - + "3d6000fd5b509050506001610a51611d4d565b6040518091039082f080158015610a6c573d6000803e" - + "3d6000fd5b509050506001610a7a611d4d565b6040518091039082f080158015610a95573d6000803e" - + "3d6000fd5b509050506001610aa3611d4d565b6040518091039082f080158015610abe573d6000803e" - + "3d6000fd5b509050506001610acc611d4d565b6040518091039082f080158015610ae7573d6000803e" - + "3d6000fd5b509050506001610af5611d4d565b6040518091039082f080158015610b10573d6000803e" - + "3d6000fd5b509050506001610b1e611d4d565b6040518091039082f080158015610b39573d6000803e3d6" - + "000fd5b509050506001610b47611d4d565b6040518091039082f080158015610b62573d6000803e3d6" - + "000fd5b509050506001610b70611d4d565b6040518091039082f080158015610b8b573d6000803e3d6000" - + "fd5b509050506001610b99611d4d565b6040518091039082f080158015610bb4573d6000803e3d6000fd5b5" - + "09050506001610bc2611d4d565b6040518091039082f080158015610bdd573d6000803e3d6000fd5b5090" - + "50506001610beb611d4d565b6040518091039082f080158015610c06573d6000803e3d6000fd5b509050" - + "506001610c14611d4d565b6040518091039082f080158015610c2f573d6000803e3d6000fd5b50905050" - + "6001610c3d611d4d565b6040518091039082f080158015610c58573d6000803e3d6000fd5b509050506" - + "001610c66611d4d565b6040518091039082f080158015610c81573d6000803e3d6000fd5b50905050600" - + "1610c8f611d4d565b6040518091039082f080158015610caa573d6000803e3d6000fd5b5090505060016" - + "10cb8611d4d565b6040518091039082f080158015610cd3573d6000803e3d6000fd5b509050506001610c" - + "e1611d4d565b6040518091039082f080158015610cfc573d6000803e3d6000fd5b509050506001610d0a6" - + "11d4d565b6040518091039082f080158015610d25573d6000803e3d6000fd5b509050506001610d33611d" - + "4d565b6040518091039082f080158015610d4e573d6000803e3d6000fd5b509050506001610d5c611d4d5" - + "65b6040518091039082f080158015610d77573d6000803e3d6000fd5b509050506001610d85611d4d565b" - + "6040518091039082f080158015610da0573d6000803e3d6000fd5b509050506001610dae611d4d565b604" - + "0518091039082f080158015610dc9573d6000803e3d6000fd5b509050506001610dd7611d4d565b604051" - + "8091039082f080158015610df2573d6000803e3d6000fd5b509050506001610e00611d4d565b604051809" - + "1039082f080158015610e1b573d6000803e3d6000fd5b509050506001610e29611d4d565b604051809103" - + "9082f080158015610e44573d6000803e3d6000fd5b509050506001610e52611d4d565b604051809103908" - + "2f080158015610e6d573d6000803e3d6000fd5b509050506001610e7b611d4d565b6040518091039082f0" - + "80158015610e96573d6000803e3d6000fd5b509050506001610ea4611d4d565b6040518091039082f080" - + "158015610ebf573d6000803e3d6000fd5b509050506001610ecd611d4d565b6040518091039082f08015" - + "8015610ee8573d6000803e3d6000fd5b5091505073ffffffffffffffffffffffffffffffffffffffff82" - + "16ff5b6001610f0f611d4d565b6040518091039082f080158015610f2a573d6000803e3d6000fd5b5090" - + "50506001610f38611d4d565b6040518091039082f080158015610f53573d6000803e3d6000fd5b509050" - + "506001610f61611d4d565b6040518091039082f080158015610f7c573d6000803e3d6000fd5b50905050" - + "6001610f8a611d4d565b6040518091039082f080158015610fa5573d6000803e3d6000fd5b5090505060" - + "01610fb3611d4d565b6040518091039082f080158015610fce573d6000803e3d6000fd5b5090505060016" - + "10fdc611d4d565b6040518091039082f080158015610ff7573d6000803e3d6000fd5b509050506001611" - + "005611d4d565b6040518091039082f080158015611020573d6000803e3d6000fd5b50905050600161102" - + "e611d4d565b6040518091039082f080158015611049573d6000803e3d6000fd5b5090505060016110576" - + "11d4d565b6040518091039082f080158015611072573d6000803e3d6000fd5b509050506001611080611d" - + "4d565b6040518091039082f08015801561109b573d6000803e3d6000fd5b5090505060016110a9611d4d5" - + "65b6040518091039082f0801580156110c4573d6000803e3d6000fd5b5090505060016110d2611d4d565b" - + "6040518091039082f0801580156110ed573d6000803e3d6000fd5b5090505060016110fb611d4d565b604" - + "0518091039082f080158015611116573d6000803e3d6000fd5b509050506001611124611d4d565b604051" - + "8091039082f08015801561113f573d6000803e3d6000fd5b50905050600161114d611d4d565b604051809" - + "1039082f080158015611168573d6000803e3d6000fd5b509050506001611176611d4d565b604051809103" - + "9082f080158015611191573d6000803e3d6000fd5b50905050600161119f611d4d565b6040518091039082" - + "f0801580156111ba573d6000803e3d6000fd5b5090505060016111c8611d4d565b6040518091039082f0801" - + "580156111e3573d6000803e3d6000fd5b5090505060016111f1611d4d565b6040518091039082f0801580" - + "1561120c573d6000803e3d6000fd5b50905050600161121a611d4d565b6040518091039082f0801580156" - + "11235573d6000803e3d6000fd5b509050506001611243611d4d565b6040518091039082f0801580156112" - + "5e573d6000803e3d6000fd5b50905050600161126c611d4d565b6040518091039082f0801580156112875" - + "73d6000803e3d6000fd5b509050506001611295611d4d565b6040518091039082f0801580156112b0573" - + "d6000803e3d6000fd5b5090505060016112be611d4d565b6040518091039082f0801580156112d9573d6" - + "000803e3d6000fd5b5090505060016112e7611d4d565b6040518091039082f080158015611302573d600" - + "0803e3d6000fd5b509050506001611310611d4d565b6040518091039082f08015801561132b573d60008" - + "03e3d6000fd5b509050506001611339611d4d565b6040518091039082f080158015611354573d6000803" - + "e3d6000fd5b509050506001611362611d4d565b6040518091039082f08015801561137d573d6000803e3d" - + "6000fd5b50905050600161138b611d4d565b6040518091039082f0801580156113a6573d6000803e3d60" - + "00fd5b5090505060016113b4611d4d565b6040518091039082f0801580156113cf573d6000803e3d6000" - + "fd5b5090505060016113dd611d4d565b6040518091039082f0801580156113f8573d6000803e3d6000fd" - + "5b509050506001611406611d4d565b6040518091039082f080158015611421573d6000803e3d6" - + "000fd5b50905050600161142f611d4d565b6040518091039082f08015801561144a573d6000803" - + "e3d6000fd5b509050506001611458611d4d565b6040518091039082f080158015611473573d6000" - + "803e3d6000fd5b509050506001611481611d4d565b6040518091039082f08015801561149c573d6000" - + "803e3d6000fd5b5090505060016114aa611d4d565b6040518091039082f0801580156114c5573d6000" - + "803e3d6000fd5b5090505060016114d3611d4d565b6040518091039082f0801580156114ee573d6000" - + "803e3d6000fd5b5090505060016114fc611d4d565b6040518091039082f080158015611517573d6000" - + "803e3d6000fd5b509050506001611525611d4d565b6040518091039082f080158015611540573d6000" - + "803e3d6000fd5b50905050600161154e611d4d565b6040518091039082f080158015611569573d6000" - + "803e3d6000fd5b509050506001611577611d4d565b6040518091039082f080158015611592573d6000" - + "803e3d6000fd5b5090505060016115a0611d4d565b6040518091039082f0801580156115bb573d6000" - + "803e3d6000fd5b5090505060016115c9611d4d565b6040518091039082f0801580156115e4573d6000" - + "803e3d6000fd5b5090505060016115f2611d4d565b6040518091039082f08015801561160d573d6000" - + "803e3d6000fd5b50905050600161161b611d4d565b6040518091039082f080158015611636573d6000803" - + "e3d6000fd5b509050506001611644611d4d565b6040518091039082f08015801561165f573d6000803e3d" - + "6000fd5b50905050600161166d611d4d565b6040518091039082f080158015611688573d6000803e3d600" - + "0fd5b509050506001611696611d4d565b6040518091039082f0801580156116b1573d6000803e3d6000fd" - + "5b5090505060016116bf611d4d565b6040518091039082f0801580156116da573d6000803e3d6000fd5b5" - + "090505060016116e8611d4d565b6040518091039082f080158015611703573d6000803e3d6000fd5b50905" - + "0506001611711611d4d565b6040518091039082f08015801561172c573d6000803e3d6000fd5b509050506" - + "00161173a611d4d565b6040518091039082f080158015611755573d6000803e3d6000fd5b5090505060016" - + "11763611d4d565b6040518091039082f08015801561177e573d6000803e3d6000fd5b50905050600161178" - + "c611d4d565b6040518091039082f0801580156117a7573d6000803e3d6000fd5b5090505060016117b5611" - + "d4d565b6040518091039082f0801580156117d0573d6000803e3d6000fd5b5090505060016117de611d4d5" - + "65b6040518091039082f0801580156117f9573d6000803e3d6000fd5b509050506001611807611d4d565b" - + "6040518091039082f080158015611822573d6000803e3d6000fd5b509050506001611830611d4d565b604" - + "0518091039082f08015801561184b573d6000803e3d6000fd5b509050506001611859611d4d565b6040518" - + "091039082f080158015611874573d6000803e3d6000fd5b509050506001611882611d4d565b60405180910" - + "39082f08015801561189d573d6000803e3d6000fd5b5090505060016118ab611d4d565b60405180910390" - + "82f0801580156118c6573d6000803e3d6000fd5b5090505060016118d4611d4d565b6040518091039082f" - + "0801580156118ef573d6000803e3d6000fd5b5090505060016118fd611d4d565b6040518091039082f080" - + "158015611918573d6000803e3d6000fd5b509050506001611926611d4d565b6040518091039082f080158" - + "015611941573d6000803e3d6000fd5b50905050600161194f611d4d565b6040518091039082f080158015" - + "61196a573d6000803e3d6000fd5b509050506001611978611d4d565b6040518091039082f080158" - + "015611993573d6000803e3d6000fd5b5090505060016119a1611d4d565b6040518091039082f080" - + "1580156119bc573d6000803e3d6000fd5b5090505060016119ca611d4d565b6040518091039082f0" - + "801580156119e5573d6000803e3d6000fd5b5090505060016119f3611d4d565b6040518091039082f080" - + "158015611a0e573d6000803e3d6000fd5b509050506001611a1c611d4d565b6040518091039082f080" - + "158015611a37573d6000803e3d6000fd5b509050506001611a45611d4d565b6040518091039082f08015" - + "8015611a60573d6000803e3d6000fd5b509050506001611a6e611d4d565b6040518091039082f080158" - + "015611a89573d6000803e3d6000fd5b509050506001611a97611d4d565b6040518091039082f080158015" - + "611ab2573d6000803e3d6000fd5b509050506001611ac0611d4d565b6040518091039082f0801580" - + "15611adb573d6000803e3d6000fd5b509050506001611ae9611d4d565b6040518091039082f0801580156" - + "11b04573d6000803e3d6000fd5b509050506001611b12611d4d565b6040518091039082f080158015611" - + "b2d573d6000803e3d6000fd5b509050506001611b3b611d4d565b6040518091039082f080158015611b56" - + "573d6000803e3d6000fd5b509050506001611b64611d4d565b6040518091039082f080158015611b7f573" - + "d6000803e3d6000fd5b509050506001611b8d611d4d565b6040518091039082f080158015611ba8573d6" - + "000803e3d6000fd5b509050506001611bb6611d4d565b6040518091039082f080158015611bd1573d6000" - + "803e3d6000fd5b509050506001611bdf611d4d565b6040518091039082f080158015611bfa573d6000803" - + "e3d6000fd5b509050506001611c08611d4d565b6040518091039082f080158015611c23573d6000803e3" - + "d6000fd5b509050506001611c31611d4d565b6040518091039082f080158015611c4c573d6000803e3d" - + "6000fd5b509050506001611c5a611d4d565b6040518091039082f080158015611c75573d6000803e3d60" - + "00fd5b509050506001611c83611d4d565b6040518091039082f080158015611c9e573d6000803e3d6000" - + "fd5b509050506001611cac611d4d565b6040518091039082f080158015611cc7573d6000803e3d6000fd" - + "5b509050506001611cd5611d4d565b6040518091039082f080158015611cf0573d6000803e3d6000fd5b" - + "509050506001611cfe611d4d565b6040518091039082f080158015611d19573d6000803e3d6000fd5b5" - + "09050506001611d27611d4d565b6040518091039082f080158015611d42573d6000803e3d6000fd5b505" - + "050565b60005481565b60405161019080611d5e833901905600608060405260008055610179806100176" - + "000396000f3006080604052600436106100615763ffffffff7c010000000000000000000000000000000" - + "000000000000000000000000060003504166312065fe081146100635780631d1537e51461008a5780632" - + "6121ff0146100bd5780634e70b1dc146100d9575b005b34801561006f57600080fd5b506100786100ee5" - + "65b60408051918252519081900360200190f35b34801561009657600080fd5b5061006173ffffffffffff" - + "ffffffffffffffffffffffffffff6004351660243515156100f3565b6100c5610142565b604080519115" - + "158252519081900360200190f35b3480156100e557600080fd5b50610078610147565b303190565b604" - + "05173ffffffffffffffffffffffffffffffffffffffff83169060009060019082818181858883f193505" - + "05050158015610132573d6000803e3d6000fd5b50801561013e57600080fd5b5050565b600190565b600" - + "054815600a165627a7a723058202882d0005491029200e2d136284a8a3c8be01cf5b0c7350b803d8ac3" - + "7f6c80390029a165627a7a72305820f23a939c05a51e55633a86a551f2374d4248da11b9ee6cc2" - + "7949ba68a25c78af0029"; - String abi = "[{\"constant\":false,\"inputs\":[],\"name\":\"getBalance\",\"outputs\"" - + ":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\"" - + ":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name" - + "\":\"Address\",\"type\":\"address\"}],\"name\":\"transfer\",\"outputs\":[],\"payable" - + "\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false," - + "\"inputs\":[],\"name\":\"transfer2\",\"outputs\":[],\"payable\":true,\"stateMutability" - + "\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"" - + "num\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"" - + "stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true," - + "\"stateMutability\":\"payable\",\"type\":\"constructor\"}]"; + String filePath = "src/test/resources/soliditycode/" + + "contractInternalTransaction003testInternalTransaction017.sol"; + String contractName = "A"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, internalTxsAddress, blockingStubFull); @@ -886,14 +438,14 @@ public void testInternalTransaction017() { infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); Assert.assertTrue(infoById.get().getResultValue() == 0); int transactionsCount = infoById.get().getInternalTransactionsCount(); - Assert.assertEquals(89, transactionsCount); + Assert.assertEquals(77, transactionsCount); for (int i = 0; i < transactionsCount; i++) { Assert.assertFalse(infoById.get().getInternalTransactions(i).getRejected()); } Assert.assertEquals("suicide", ByteArray - .toStr(infoById.get().getInternalTransactions(88).getNote().toByteArray())); - Assert.assertEquals(1000000 - 88, - infoById.get().getInternalTransactions(88).getCallValueInfo(0).getCallValue()); + .toStr(infoById.get().getInternalTransactions(76).getNote().toByteArray())); + Assert.assertEquals(1000000 - 76, + infoById.get().getInternalTransactions(76).getCallValueInfo(0).getCallValue()); for (int i = 0; i < transactionsCount - 1; i++) { Assert.assertEquals("create", ByteArray .toStr(infoById.get().getInternalTransactions(i).getNote().toByteArray())); @@ -903,7 +455,7 @@ public void testInternalTransaction017() { dupInternalTrsansactionHash(infoById.get().getInternalTransactionsList()); } - @Test(enabled = false, description = "Test maxfeelimit can trigger call create call max time") + @Test(enabled = true, description = "Test maxfeelimit can trigger call create call max time") public void testInternalTransaction018() { Assert.assertTrue(PublicMethed .sendcoin(internalTxsAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, @@ -911,365 +463,34 @@ public void testInternalTransaction018() { PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName = "AAContract"; - String code = "6080604052612fea806100136000396000f3006080604052600436106100275763ffffffff60e0" - + "60020a60003504166363f76a6a8114610029575b005b610027600160a060020a0360043581169060243" - + "51681600160a060020a031660016040518080600080516020612f9f833981519152815250600f0" - + "19050604051809103902060e060020a900490836040518363ffffffff1660e060020a028" - + "1526004018082600160a060020a0316600160a060020a03168152602001915050600060405180830" - + "38185885af193505050505081600160a060020a031660016040518080600080516020612f9f833981519" - + "152815250600f019050604051809103902060e060020a900490836040518363ffffffff1660e" - + "060020a0281526004018082600160a060020a0316600160a060020a031681526020019150506000604051" - + "8083038185885af193505050505081600160a060020a031660016040518080600080516020612f9f8" - + "33981519152815250600f019050604051809103902060e060020a900490836040518363ffffffff16" - + "60e060020a0281526004018082600160a060020a0316600160a060020a031681526020019150506000" - + "6040518083038185885af193505050505081600160a060020a031660016040518080600080516020" - + "612f9f833981519152815250600f019050604051809103902060e060020a900490836040518363fff" - + "fffff1660e060020a0281526004018082600160a060020a0316600160a060020a031681526020019" - + "1505060006040518083038185885af193505050505081600160a060020a0316600160405180806000805" - + "16020612f9f833981519152815250600f019050604051809103902060e060020a900490836040518363" - + "ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915" - + "05060006040518083038185885af193505050505081600160a060020a0316600160405180806000805" - + "16020612f9f833981519152815250600f019050604051809103902060e060020a900490836040518" - + "363ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a0316815260200191" - + "505060006040518083038185885af193505050505081600160a060020a0316600160405180" - + "80600080516020612f9f833981519152815250600f019050604051809103902060e060020a9004908360" - + "40518363ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a031681" - + "5260200191505060006040518083038185885af193505050505081600160a060020a0316600160405" - + "18080600080516020612f9f833981519152815250600f019050604051809103902060e060020a90049" - + "0836040518363ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a031" - + "6815260200191505060006040518083038185885af193505050505081600160a060020a0316600160405" - + "18080600080516020612f9f833981519152815250600f019050604051809103902060e060020a90049083" - + "6040518363ffffffff1660e060020a0281526004018082600160a060020a0316600160a0" - + "60020a0316815260200191505060006040518083038185885af193505050505081600160a060020a0316" - + "60016040518080600080516020612f9f833981519152815250600f019050604051809103902060e060020" - + "a900490836040518363ffffffff1660e060020a0281526004018082600160a060020a0316600160a06002" - + "0a0316815260200191505060006040518083038185885af193505050505081600160a060020a031660016" - + "040518080600080516020612f9f833981519152815250600f019050604051809103902060e060020a9004" - + "90836040518363ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a031" - + "6815260200191505060006040518083038185885af193505050505081600160a060020a03166001604051" - + "8080600080516020612f9f833981519152815250600f019050604051809103902060e060020a900490836" - + "040518363ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152" - + "60200191505060006040518083038185885af193505050505081600160a060020a0316600160405180806" - + "00080516020612f9f833981519152815250600f019050604051809103902060e060020a90049083604051" - + "8363ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a0316815260200" - + "191505060006040518083038185885af193505050505081600160a060020a0316600160405180806000" - + "80516020612f9f833981519152815250600f019050604051809103902060e060020a9004908360405183" - + "63ffffffff1660e060020a0281526004018082600160a060020a03166001" - + "60a060020a0316815260200191505060006040518083038185885af19350505050508160016" - + "0a060020a031660016040518080600080516020612f9f833981519152815250600f0190506040" - + "51809103902060e060020a900490836040518363ffffffff1660e060020a0281526004018082600160a0" - + "60020a0316600160a060020a0316815260200191505060006040518083038185885af19350505050" - + "5081600160a060020a031660016040" - + "518080600080516020612f9f833981519152815250600f019050604051809103902060e060020a900490836" - + "040518363ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152" - + "60200191505060006040518083038185885af193505050505081600160a060020a031660016040518080" - + "600080516020612f9f833981519152815250600f019050604051809103902060e060020a900490836040" - + "518363ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a0316815260" - + "200191505060006040518083038185885af193505050505081600160a060020" - + "a031660016040518080600080516020612f9f833981519152815250600f019050604051809103902060e0" - + "60020a900490836040518363ffffffff1660e060020a0281526004018082600160a060020a0316600160a0" - + "60020a0316815260200191505060006040518083038185885af193505050505081600160a060020a0316" - + "60016040518080600080516020612f9f833981519152815250600f019050604051809103902060e060020" - + "a900490836040518363ffffffff1660e060020a0281526004018082600160a060020a0316600160a06002" - + "0a0316815260200191505060006040518083038185885af1935050505050816" - + "00160a060020a031660016040518080600080516020612f9f833981519152815250600f0190506040518" - + "09103902060e060020a900490836040518363ffffffff1660e060020a0281526004018082600160a060020" - + "a0316600160a060020a0316815260200191505060006040518083038185885af193505050505081600160" - + "a060020a031660016040518080600080516020612f9f833981519152815250600f0190506040518091039" - + "02060e060020a900490836040518363ffffffff1660e060020a0281526004018082600160a060020a0316" - + "600160a060020a0316815260200191505060006040518083038185885af193505050505081600160a060" - + "020a031660016040518080600080516020612f9f833981519152815250600f019050604051809103902" - + "060e060020a900490836040518363ffffffff1660e060020a0281526004018082600160a060020a03166" - + "00160a060020a0316815260200191505060006040518083038185885af193505050505081600160a0600" - + "20a031660016040518080600080516020612f9f833981519152815250600f019050604051809103902060" - + "e060020a900490836040518363ffffffff1660e060020a0281526004018082600160a060020a031660" - + "0160a060020a0316815260200191505060006040518083038185885af193505050505081600160a0600" - + "20a031660016040518080600080516020612f9f833981519152815250600f01905060405180910390206" - + "0e060020a900490836040518363ffffffff1660e060020a0281526004018082600160a060020a031660" - + "0160a060020a0316815260200191505060006040518083038185885af193505050505081600160a060020" - + "a031660016040518080600080516020612f9f833981519152815250600f019050604051809103902060e" - + "060020a900490836040518363ffffffff1660e060020a0281526004018082600160a060020a0316600160" - + "a060020a0316815260200191505060006040518083038185885af193505050505081600160a060020a03" - + "1660016040518080600080516020612f9f833981519152815250600f019050604051809103902060e0600" - + "20a900490836040518363ffffffff1660e060020a0281526004018082600160a060020a0316600160a0600" - + "20a0316815260200191505060006040518083038185885af193505050505081600160a060020a031660016" - + "040518080600080516020612f9f833981519152815250600f019050604051809103902060e060020a9004" - + "90836040518363ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a031" - + "6815260200191505060006040518083038185885af193505050505081600160a060020a03166001604051" - + "8080600080516020612f9f833981519152815250600f019050604051809103902060e060020a900490836" - + "040518363ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152" - + "60200191505060006040518083038185885af193505050505081600160a060020a0316600160405180806" - + "00080516020612f9f833981519152815250600f019050604051809103902060e060020a90049083604051" - + "8363ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a0316815260200" - + "191505060006040518083038185885af193505050505081600160a060020a031660016040518" - + "080600080516020612f9f833981519152815250600f019050604051809103902060e060020a900490" - + "836040518363ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a031681" - + "5260200191505060006040518083038185885af193505050505081600160a060020a03166001604051808" - + "0600080516020612f9f833981519152815250600f019050604051809103902060e060020a9004908360" - + "40518363ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a031681" - + "5260200191505060006040518083038185885af193505050505081600160a060020a0316600160405180" - + "80600080516020612f9f833981519152815250600f019050604051809103902060e060020a90049083604" - + "0518363ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a0316815260" - + "200191505060006040518083038185885af193505050505081600160a060020a0316600160405180806" - + "00080516020612f9f833981519152815250600f019050604051809103902060e060020a900490836040" - + "518363ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a0316815260" - + "200191505060006040518083038185885af193505050505081600160a060020a0316600160405180806000" - + "80516020612f9f833981519152815250600f019050604051809103902060e060020a900490836040518363" - + "ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915" - + "05060006040518083038185885af193505050505081600160a060020a0316600160405180806000805160" - + "20612f9f833981519152815250600f019050604051809103902060e060020a900490836040518363f" - + "fffffff1660e060020a0281526004018082600160a060020a0316600160a060020a0316815260200191505" - + "060006040518083038185885af193505050505081600160a060020a031660016040518080600080516020" - + "612f9f833981519152815250600f019050604051809103902060e060020a900490836040518363ff" - + "ffffff1660e060020a0281526004018082" - + "600160a060020a0316600160a060020a0316815260200191505060006040518083038185885af1935050" - + "50505081600160a060020a031660016040518080600080516020612f9f833981519152815250600f01905" - + "0604051809103902060e060020a900490836040518363ffffffff1660e060020a028152600401808260016" - + "0a060020a0316600160a060020a0316815260200191505060006040518083038185885af1935050505050" - + "81600160a060020a031660016040518080600080516020612f9f833981519152815250600f0190506040" - + "51809103902060e060020a900490836040518363ffffffff1660e060020a0281526004018082600160a06" - + "0020a0316600160a060020a0316815260200191505060006040518083038185885af193505050505081600" - + "160a060020a031660016040518080600080516020612f9f833981519152815250600f019050604051809103" - + "902060e060020a900490836040518363ffffffff1660e060020a0281526004018082600160a060020a031" - + "6600160a060020a0316815260200191505060006040518083038185885af193505050505081600160a06" - + "0020a031660016040518080600080516020612f9f833981519152815250600f019050604051809" - + "103902060e060020a900490836040518363ffffffff1660e060020a0281526004018082600160a06" - + "0020a0316600160a060020a0316815260200191505060006040518083038185885af193505050505" - + "081600160a060020a031660016040518080600080516020612f9f833981519152815250600f019050604" - + "051809103902060e060020a900490836040518363ffffffff1660e060020a0281526004018082600160a" - + "060020a0316600160a060020a0316815260200191505060006040518083038185885af1935050505050" - + "81600160a060020a031660016040518080600080516020612f9f833981519152815250600f019050604" - + "051809103902060e060020a900490836040518363ffffffff1660e060020a0281526004018082600160" - + "a060020a0316600160a060020a0316815260200191505060006040518083038185885af1935050505050" - + "81600160a060020a031660016040518080600080516020612f9f833981519152815250600f019050604051" - + "809103902060e060020a900490836040518363ffffffff1660e060020a0281526004018082600160a06002" - + "0a0316600160a060020a0316815260200191505060006040518083038185885af19350505050508160016" - + "0a060020a031660016040518080600080516020612f9f833981519152815250600f019050604051809103" - + "902060e060020a900490836040518363ffffffff1660e060020a0281526004018082600160a060020a031" - + "6600160a060020a0316815260200191505060006040518083038185885af193505050505081600160a06" - + "0020a031660016040518080600080516020612f9f833981519152815250600f019050604051809103902" - + "060e060020a900490836040518363ffffffff1660e060020a0281526004018082600160a060020a031660" - + "0160a060020a0316815260200191505060006040518083038185885af193505050505081600160a060020" - + "a031660016040518080600080516020612f9f833981519152815250600f0190506040518091039020" - + "60e060020a900490836040518363ffffffff1660e060020a0281526004018082600160a060020a03166" - + "00160a060020a0316815260200191505060006040518083038185885af193505050505081600160a060" - + "020a031660016040518080600080516020612f9f833981519152815250600f019050604051809103902" - + "060e060020a900490836040518363ffffffff1660e060020a0281526004018082600160a060020a0316" - + "600160a060020a0316815260200191505060006040518083038185885af193505050505081600160a06" - + "0020a031660016040518080600080516020612f9f833981519152815250600f019050604051809103902" - + "060e060020a900490836040518363ffffffff1660e060020a0281526004018082600160a060020a031660" - + "0160a060020a0316815260200191505060006040518083038185885af193505050505081600160a060020" - + "a031660016040518080600080516020612f9f833981519152815250600f0190506040518091039020" - + "60e060020a900490836040518363ffffffff1660e060020a0281526004018082600160a060020a031" - + "6600160a060020a0316815260200191505060006040518083038185885af193505050505081600160" - + "a060020a031660016040518080600080516020612f9f833981519152815250600f019050604051809" - + "103902060e060020a900490836040518363ffffffff1660e060020a0281526004018082600160a060" - + "020a031660" - + "0160a060020a0316815260200191505060006040518083038185885af19350505050508160" - + "0160a060020a031660016040518080600080516020612f9f833981519152815250600f0190506" - + "04051809103902060e060020a900490836040518363ffffffff1660e060020a02815260040180826001" - + "60a060020a0316600160a060020a0316815260200191505060006040518083038185885af193505050" - + "505081600160a060020a031660016040518080600080516020612f9f833981519152815250600f0" - + "19050604051809103902060e060020a900490836040518363ffffffff1660e060020a02815260040" - + "18082600160a060020a0316600160a060020a0316815260200191505060006040518083038185885a" - + "f193505050505081600160a060020a031660016040518080600080516020612f9f833981519152815" - + "250600f019050604051809103902060e060020a900490836040518363ffffffff1660e060020a0281" - + "526004018082600160a060020a0316600160a060020a0316815260200191505060006040518083038" - + "185885af193505050505081600160a060020a031660016040518080600080516020612f9f833981519" - + "152815250600f019050604051809103902060e060020a900490836040518363ffffffff1660e060020" - + "a0281526004018082600160a060020a0316600160a060020a031681526020019150506000604051808" - + "3038185885af193505050505081600160a060020a031660016040518080600080516020612f9f83398" - + "1519152815250600f019050604051809103902060e060020a900490836040518363ffffffff1660e06" - + "0020a0281526004018082600160a060020a0316600160a060020a03168152602001915050600060405" - + "18083038185885af193505050505081600160a060020a031660016040518080600080516020612f9f8" - + "33981519152815250600f019050604051809103902060e060020a900490836040518363ffffffff166" - + "0e060020a0281526004018082600160a060020a0316600160a060020a0316815260200191505060006" - + "040518083038185885af193505050505081600160a060020a031660016040518080600080516020612" - + "f9f833981519152815250600f019050604051809103902060e060020a900490836040518363fffffff" - + "f1660e060020a0281526004018082600160a060020a0316600160a060020a031681526020019150506" - + "0006040518083038185885af193505050505081600160a060020a031660016040518080600080516020" - + "612f9f833981519152815250600f019050604051809103902060e060020a900490836040518363fff" - + "fffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915" - + "05060006040518083038185885af193505050505081600160a060020a0316600160405180806000805" - + "16020612f9f833981519152815250600f019050604051809103902060e060020a90049083604051836" - + "3ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a031681526020" - + "0191505060006040518083038185885af193505050505081600160a060020a0316600160405180806" - + "00080516020612f9f833981519152815250600f019050604051809103902060e060020a900490836040" - + "518363ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152" - + "60200191505060006040518083038185885af193505050505081600160a060020a0316600160405180" - + "80600080516020612f9f833981519152815250600f019050604051809103902060e060020a900490836" - + "040518363ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168" - + "15260200191505060006040518083038185885af193505050505081600160a060020a0316600160405" - + "18080600080516020612f9f833981519152815250600f019050604051809103902060e060020a900490" - + "836040518363ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a031" - + "6815260200191505060006040518083038185885af193505050505081600160a060020a031660016040" - + "518080600080516020612f9f833981519152815250600f019050604051809103902060e060020a90049" - + "0836040518363ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03" - + "16815260200191505060006040518083038185885af193505050505081600160a060020a03166001604" - + "0518080600080516020612f9f833981519152815250600f019050604051809103902060e060020a9004" - + "90836040518363ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03" - + "16815260200191505060006040518083038185885af193505050505081600160a060020a031660016040" - + "518080600080516020612f9f833981519152815250600f019050604051809103902060e060020a9004908" - + "36040518363ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a031681" - + "5260200191505060006040518083038185885af193505050505081600160a060020a031660016040518" - + "080600080516020612f9f833981519152815250600f019050604051809103902060e060020a900490836" - + "040518363ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a0316815" - + "260200191505060006040518083038185885af193505050505081600160a060020a03166001604051808" - + "0600080516020612f9f833981519152815250600f019050604051809103902060e060020a9004908360405" - + "18363ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a0316815260200" - + "191505060006040518083038185885af193505050505081600160a060020a0316600160405180806" - + "00080516020612f9f833981519152815250600f019050604051809103902060e060020a900" - + "490836040518363fffff" - + "fff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050" - + "60006040518083038185885af193505050505081600160a060020a03166001604051808060008051602" - + "0612f9f833981519152815250600f019050604051809103902060e060020a900490836040518363f" - + "fffffff1660e060020a0281526004018082600160a060020a0316600160a060020a031681" - + "52602001915050600060" - + "40518083038185885af193505050505081600160a060020a031660016040518080600080516020612f" - + "9f833981519152815250600f019050604051809103902060e060020a900490836040518363ffffffff1" - + "660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050600" - + "06040518083038185885af193505050505081600160a060020a03166001604051808060008051602061" - + "2f9f833981519152815250600f019050604051809103902060e060020a900490836040518363ffffffff1" - + "660e060020a0281526004018082600160a060020a0316600160a060020a031681526020019150506000604" - + "0518083038185885af193505050505081600160a060020a031660016040518080600080516020612f9f833" - + "981519152815250600f019050604051809103902060e060020a900490836040518363ffffffff1660e0600" - + "20a0281526004018082600160a060020a0316600160a060020a03168152602001915050600060405180830" - + "38185885af193505050505081600160a060020a031660016040518080600080516020612f9f833" - + "981519152815250600f019050604051809103902060e060020a900490836040518363ffffffff1" - + "660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050" - + "60006040518083038185885af193505050505081600160a060020a03166001604051808060008051" - + "6020612f9f833981519152815250600f019050604051809103902060e060020a90049083604051836" - + "3ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a031681526020" - + "0191505060006040518083038185885af193505050505081600160a060020a03166001604051808060" - + "0080516020612f9f833981519152815250600f019050604051809103902060e060020a900490836040" - + "518363ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a031681526" - + "0200191505060006040518083038185885af193505050505081600160a060020a031660016040518080" - + "600080516020612f9f833981519152815250600f019050604051809103902060e060020a90049083604" - + "0518363ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a031681526" - + "0200191505060006040518083038185885af193505050505081600160a060020a0316600160405180806" - + "00080516020612f9f833981519152815250600f019050604051809103902060e060020a90049083604051" - + "8363ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152" - + "60200191505060006040518083038185885af193505050505081600160a060020a031660016040518" - + "080600080516020612f9f833981519152815250600f019050604051809103902060e060020a9004908" - + "36040518363ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a0316" - + "815260200191505060006040518083038185885af193505050505081600160a060020a0316600160405" - + "18080600080516020612f9f833981519152815250600f019050604051809103902060e060020a9004" - + "90836040518363ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a031" - + "6815260200191505060006040518083038185885af193505050505081600160a060020a031660016040518" - + "080600080516020612f9f833981519152815250600f019050604051809103902060e060020a90049083604" - + "0518363ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602" - + "00191505060006040518083038185885af193505050505081600160a060020a03166001604051808060008" - + "0516020612f9f833981519152815250600f019050604051809103902060e060020a900490836040518363f" - + "fffffff1660e060020a0281526004018082600160a060020a0316600160a060020a0316815260200191505" - + "060006040518083038185885af193505050505081600160a060020a0316600160405180806000805160206" - + "12f9f833981519152815250600f019050604051809103902060e060020a900490836040518363ffffffff1" - + "660e060020a0281526004018082600160a060020a0316600160a060020a031681526020019150506000604" - + "0518083038185885af193505050505081600160a060020a031660016040518080600080516020612f9f83" - + "3981519152815250600f019050604051809103902060e060020a900490836040518363ffffffff1660e06" - + "0020a0281526004018082600160a060020a0316600160a060020a03168152602001915050600060405180" - + "83038185885af193505050505081600160a060020a031660016040518080600080516020612f9f8339815" - + "19152815250600f019050604051809103902060e060020a900490836040518363ffffffff1660e060020a" - + "0281526004018082600160a060020a0316600160a060020a0316815260200191505060006040518083038" - + "185885af193505050505081600160a060020a031660016040518080600080516020612f9f833981519152" - + "815250600f019050604051809103902060e060020a900490836040518363ffffffff1660e060020a02815" - + "26004018082600160a060020a0316600160a060020a0316815260200191505060006040518083" - + "038185885af193505050505081600160a060020a0316600160405180" - + "80600080516020612f9f833981519152815250600f019050604051809103902060e060020a90049083604" - + "0518363ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a0316815260" - + "200191505060006040518083038185885af193505050505081600160a060020a031660016040518080600" - + "080516020612f9f833981519152815250600f019050604051809103902060e060020a90049083604051836" - + "3ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915" - + "05060006040518083038185885af193505050505081600160a060020a031660016040518080600080516" - + "020612f9f833981519152815250600f019050604051809103902060e060020a900490836040518363fffff" - + "fff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050600" - + "06040518083038185885af193505050505081600160a060020a031660016040518080600080516020612f9" - + "f833981519152815250600f019050604051809103902060e060020a900490836040518363ffffffff1660e" - + "060020a0281526004018082600160a060020a0316600160a060020a031681526020019150506000604051" - + "8083038185885af193505050505081600160a060020a031660016040518080600080516020612f9f8339" - + "81519152815250600f019050604051809103902060e060020a900490836040518363ffffffff1660e060" - + "020a0281526004018082600160a060020a0316600160a060020a03168152602001915050600060405180" - + "83038185885af193505050505081600160a060020a031660016040518080600080516020612f9f83398" - + "1519152815250600f019050604051809103902060e060020a900490836040518363ffffffff1660e0600" - + "20a0281526004018082600160a060020a0316600160a060020a031681526020019150506000604051808" - + "3038185885af193505050505081600160a060020a031660016040518080600080516020612f9f8339815" - + "19152815250600f019050604051809103902060e060020a900490836040518363ffffffff1660e060020" - + "a0281526004018082600160a060020a0316600160a060020a03168152602001915050600060405180830" - + "38185885af193505050505081600160a060020a031660016040518080600080516020612f9f833981519" - + "152815250600f019050604051809103902060e060020a900490836040518363ffffffff1660e060020a02" - + "81526004018082600160a060020a0316600160a060020a031681526020019150506000604051808303818" - + "5885af193505050505081600160a060020a031660016040518080600080516020612f9f83398151915281" - + "5250600f019050604051809103902060e060020a900490836040518363ffffffff1660e060020a0281526" - + "004018082600160a060020a0316600160a060020a0316815260200191505060006040518083038185885a" - + "f193505050505081600160a060020a031660016040518080600080516020612f9f8339815191528152506" - + "00f019050604051809103902060e060020a900490836040518363ffffffff1660e060020a028152600401" - + "8082600160a060020a0316600160a060020a0316815260200191505060006040518083038185885af1935" - + "05050505081600160a060020a031660016040518080600080516020612f9f833981519152815250600f01" - + "9050604051809103902060e060020a900490836040518363ffffffff1660e060020a02815260040" - + "18082600160a060020a0316600160a060020a03168152602001915050" - + "60006040518083038185885af193505050505081600160a060020a0316600160405180806000805160" - + "20612f9f833981519152815250600f019050604051809103902060e060020a900490836040518363ffff" - + "ffff1660e060020a0281526004018082600160a060020a0316600160a060020a031681526020019150506" - + "0006040518083038185885af1505050505050505600746573744e4e2861646472657373290000000000000" - + "000000000000000000000a165627a7a72305820820d0afeaca0e47724cff771d48ead1deaffee5" - + "c5e7e66e06f1abc96869dd64d0029"; - String abi = "[{\"constant\":false,\"inputs\":[{\"name\":\"bAddr\",\"type\":\"" - + "address\"},{\"name\":\"eAddr\",\"type\":\"address\"}],\"name\":\"test1\"" - + ",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\"" - + ":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\"," - + "\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"" - + "type\":\"fallback\"}]"; + String filePath = "src/test/resources/soliditycode/" + + "contractInternalTransaction003testInternalTransaction018.sol"; + String contractName = "A"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, internalTxsAddress, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName1 = "BContract"; - String code1 = "60806040526102de806100136000396000f30060806040526004361061004b5763ffff" - + "ffff7c0100000000000000000000000000000000000000000000000000000000600035041663" - + "7c0e37a6811461004d578063ab5ed1501461006e575b005b61004b73fffffffffffffffffffffff" - + "fffffffffffffffff60043516610088565b610076610180565b6040805191825251908190036020019" - + "0f35b60006103e8610095610185565b6040518091039082f0801580156100b0573d6000803e3d6000fd" - + "5b50905090508073ffffffffffffffffffffffffffffffffffffffff1663088a91f5836040518263ffff" - + "ffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273f" - + "fffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16" - + "8152602001915050602060405180830381600087803b15801561015057600080fd5b505af115801561016" - + "4573d6000803e3d6000fd5b505050506040513d602081101561017a57600080fd5b50505050565b6001905" - + "65b60405161011d80610196833901905600608060405261010a806100136000396000f300608060405260" - + "04361060255763ffffffff60e060020a600035041663088a91f581146027575b005b604673ffffffffffff" - + "ffffffffffffffffffffffffffff600435166058565b60408051918252519081900360200190f35b600081" - + "73ffffffffffffffffffffffffffffffffffffffff16600160405180807f6765745a65726f2829000000000" - + "00000000000000000000000000000000000008152506009019050604051809103902060e060020a90049" - + "06040518263ffffffff1660e060020a02815260040160006040518083038185885af193505050505091" - + "90505600a165627a7a72305820dd7a7f17b07e2480b36bc7468d984ead013aae68a1eb55dbd5f1ede715" - + "affd1e0029a165627a7a72305820cb8ab1f0fbe80c0c0e76a374dda5663ec870b576de983670" - + "35aa7606c07707a00029"; - String abi1 = "[{\"constant\":false,\"inputs\":[{\"name\":\"eAddress\",\"type\":\"" - + "address\"}],\"name\":\"testNN\",\"outputs\":[],\"payable\":true,\"stateMutability" - + "\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"" - + "getOne\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"" - + "stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":" - + "true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true" - + ",\"stateMutability\":\"payable\",\"type\":\"fallback\"}]"; + String contractName1 = "B"; + HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); + + String code1 = retMap1.get("byteCode").toString(); + String abi1 = retMap1.get("abI").toString(); byte[] contractAddress1 = PublicMethed .deployContract(contractName1, abi1, code1, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, internalTxsAddress, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName2 = "EContract"; - String code2 = "6080604052609f806100126000396000f30060806040526004361060485763ffffffff" - + "7c0100000000000000000000000000000000000000000000000000000000600035041663" - + "9f3f89dc8114604a578063fbf004e3146062575b005b60506068565b60408051918252519" - + "081900360200190f35b6050606d565b600090565b60008080fd00a165627a7a723" - + "05820fed1b0b287ea849db12d31a338942ee575c9e0bbdb07e7da09a4d432511308120029"; - String abi2 = "[{\"constant\":false,\"inputs\":[],\"name\":\"getZero\",\"outputs\"" - + ":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":" - + "\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"" - + "newBAndTransfer\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\"" - + ":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable" - + "\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"payable\":true,\"" - + "stateMutability\":\"payable\",\"type\":\"fallback\"}]"; + String contractName2 = "E"; + HashMap retMap2 = PublicMethed.getBycodeAbi(filePath, contractName2); + + String code2 = retMap2.get("byteCode").toString(); + String abi2 = retMap2.get("abI").toString(); byte[] contractAddress2 = PublicMethed .deployContract(contractName2, abi2, code2, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, @@ -1280,20 +501,22 @@ public void testInternalTransaction018() { blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); String initParmes = "\"" + Base58.encode58Check(contractAddress1) + "\",\"" + Base58.encode58Check(contractAddress2) + "\""; String txid = ""; txid = PublicMethed.triggerContract(contractAddress, "test1(address,address)", initParmes, false, - 0, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); + 100000, maxFeeLimit, internalTxsAddress, testKeyForinternalTxsAddress, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); Optional infoById = null; infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); + logger.info("InfoById:" + infoById); Assert.assertTrue(infoById.get().getResultValue() == 0); int transactionsCount = infoById.get().getInternalTransactionsCount(); - Assert.assertEquals(388, transactionsCount); + Assert.assertEquals(184, transactionsCount); for (int i = 0; i < transactionsCount; i++) { Assert.assertFalse(infoById.get().getInternalTransactions(i).getRejected()); } @@ -1316,7 +539,7 @@ public void testInternalTransaction018() { Assert.assertEquals("call", note2); Assert.assertEquals("call", note3); Assert.assertTrue(1 == vaule1); - Assert.assertTrue(1000 == vaule2); + Assert.assertTrue(100 == vaule2); Assert.assertTrue(0 == vaule3); Assert.assertTrue(1 == vaule4); diff --git a/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage001.java b/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage001.java index b7a3908cfba..3a87abf7eff 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage001.java +++ b/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage001.java @@ -2,6 +2,7 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -95,82 +96,15 @@ public void deployContentValue() { logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); //Value is equal balance,this will be failed.Only use FreeNet,Other not change. - String payableCode = "608060405260008054600160a060020a031990811662010001179091556001805482166" - + "20100021790556002805482166201000317905560038054821662010004179055600480548216620100051" - + "790556005805482166201000617905560068054909116620100071790556104ce8061007a6000396000f30" - + "06080604052600436106100da5763ffffffff7c010000000000000000000000000000000000000000000000" - + "00000000006000350416630a90265081146100df5780630dfb51ac146100fc57806345bd20101461012d578" - + "0634efaaa1b1461014257806352ae1b811461016657806353c4263f1461017b5780635fd8c710146101905" - + "780637c369c90146101a55780637f2b7f93146101ba5780638259d5531461020f578063906fbec91461022" - + "7578063961a8be71461023c578063cee14bb414610251578063ec9928bd14610275578063fb4f32aa146102" - + "92575b600080fd5b3480156100eb57600080fd5b506100fa6004356024356102a7565b005b3480156101085" - + "7600080fd5b506101116102dc565b60408051600160a060020a039092168252519081900360200190f35b3" - + "4801561013957600080fd5b506101116102eb565b34801561014e57600080fd5b506100fa600160a060020" - + "a03600435166024356102fa565b34801561017257600080fd5b50610111610320565b34801561018757600" - + "080fd5b5061011161032f565b34801561019c57600080fd5b506100fa61033e565b3480156101b15760008" - + "0fd5b5061011161035d565b3480156101c657600080fd5b506040805160206004803580820135838102808" - + "60185019096528085526100fa9536959394602494938501929182918501908490808284375094975061036" - + "c9650505050505050565b34801561021b57600080fd5b506100fa6004356103c6565b34801561023357600" - + "080fd5b506101116103f7565b34801561024857600080fd5b50610111610406565b34801561025d5760008" - + "0fd5b506100fa600160a060020a0360043516602435610415565b34801561028157600080fd5b506100fa6" - + "00435602435151561044d565b34801561029e57600080fd5b506100fa610483565b6001546040805184815" - + "2602081018490528151600160a060020a0390931692818301926000928290030181855af45050505050565" - + "b600654600160a060020a031681565b600354600160a060020a031681565b816080528060a052600060806" - + "0406080620100016000f4151561031c57600080fd5b5050565b600254600160a060020a031681565b60045" - + "4600160a060020a031681565b600354604051600160a060020a03909116906000818181855af4505050565" - + "b600554600160a060020a031681565b6005546040518251600160a060020a0390921691839190819060208" - + "08501910280838360005b838110156103aa578181015183820152602001610392565b50505050905001915" - + "050600060405180830381855af450505050565b600654604080518381529051600160a060020a039092169" - + "160208083019260009291908290030181855af450505050565b600054600160a060020a031681565b600154" - + "600160a060020a031681565b6000805460408051600160a060020a038681168252602082018690528251931" - + "69381830193909290918290030181855af45050505050565b60045460408051848152831515602082015281" - + "51600160a060020a0390931692818301926000928290030181855af45050505050565b60025460405160016" - + "0a060020a03909116906000818181855af45050505600a165627a7a72305820bf65c4013bea4495f2cbccf6" - + "85ee1442e2585d226cf4bd8184c636cdd1d485dc0029"; - String payableAbi = "[{\"constant\":false,\"inputs\":[{\"name\":\"frozen_Balance\",\"type\":" - + "\"uint256\"},{\"name\":\"frozen_Duration\",\"type\":\"uint256\"}],\"name\":\"" - + "freezeBalance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\"," - + "\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":" - + "\"deleteProposalAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}]," - + "\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":" - + "true,\"inputs\":[],\"name\":\"withdrawBalanceAddress\",\"outputs\":[{\"name\":\"\"," - + "\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":" - + "\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"witnessAddr\",\"type\"" - + ":\"address\"},{\"name\":\"voteValue\",\"type\":\"uint256\"}],\"name\":" - + "\"voteUsingAssembly\",\"outputs\":[],\"payable\":false,\"stateMutability\":" - + "\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":" - + "\"unFreezeBalanceAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}]," - + "\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":" - + "true,\"inputs\":[],\"name\":\"approveProposalAddress\",\"outputs\":[{\"name\":\"\"," - + "\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":" - + "\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"withdrawBalance\"," - + "\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":" - + "\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"createProposalAddress\"," - + "\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false," - + "\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[" - + "{\"name\":\"data\",\"type\":\"bytes32[]\"}],\"name\":\"createProposal\",\"outputs\":" - + "[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}," - + "{\"constant\":false,\"inputs\":[{\"name\":\"id\",\"type\":\"uint256\"}],\"name\":" - + "\"deleteProposal\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\"" - + ",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":" - + "\"voteContractAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}]," - + "\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":" - + "true,\"inputs\":[],\"name\":\"freezeBalanceAddress\",\"outputs\":[{\"name\":\"\"," - + "\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":" - + "\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"witnessAddr\",\"type\":" - + "\"address\"},{\"name\":\"voteValue\",\"type\":\"uint256\"}],\"name\":" - + "\"voteForSingleWitness\",\"outputs\":[],\"payable\":false,\"stateMutability\":" - + "\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"id" - + "\",\"type\":\"uint256\"},{\"name\":\"isApprove\",\"type\":\"bool\"}],\"name\":" - + "\"approveProposal\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable" - + "\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":" - + "\"unFreezeBalance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable" - + "\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"" - + "payable\",\"type\":\"constructor\"}]"; + String filePath = "./src/test/resources/soliditycode/contractLinkage001.sol"; + String contractName = "divideIHaveArgsReturnStorage"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String payableCode = retMap.get("byteCode").toString(); + String payableAbi = retMap.get("abI").toString(); PublicMethed.waitProduceNextBlock(blockingStubFull); Account accountGet = PublicMethed.queryAccount(linkage001Key, blockingStubFull); Long accountBalance = accountGet.getBalance(); - String contractName = "tronNative"; String txid = PublicMethed.deployContractAndGetTransactionInfoById(contractName, payableAbi, payableCode, "", maxFeeLimit, accountBalance, 100, null, linkage001Key, linkage001Address, blockingStubFull); diff --git a/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage005.java b/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage005.java index 3145c740743..edb0805e426 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage005.java +++ b/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage005.java @@ -2,6 +2,7 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -96,41 +97,6 @@ public void testEnergyCostDetail() { 0, 1, linkage005Key, blockingStubFull)); PublicMethed.waitProduceNextBlock(blockingStubFull); - contractName = "EnergyCost"; - code = "6080604052600060035534801561001557600080fd5b5061027b806100256000396000f300608060405260" - + "0436106100825763ffffffff7c0100000000000000000000000000000000000000000000000000000000600" - + "0350416633755cd3c81146100875780637d965688146100b1578063a05b2577146100c9578063b0d6304d14" - + "6100e1578063bbe1d75b14610115578063f8a8fd6d1461012a578063fe75faab14610141575b600080fd5b3" - + "4801561009357600080fd5b5061009f600435610159565b60408051918252519081900360200190f35b3480" - + "156100bd57600080fd5b5061009f600435610178565b3480156100d557600080fd5b5061009f60043561019" - + "8565b3480156100ed57600080fd5b5061009f73ffffffffffffffffffffffffffffffffffffffff60043581" - + "1690602435166101e2565b34801561012157600080fd5b5061009f6101ff565b34801561013657600080fd5" - + "b5061013f610205565b005b34801561014d57600080fd5b5061009f600435610218565b6000805482908110" - + "61016757fe5b600091825260209091200154905081565b600080805b8381101561019157600191820191016" - + "1017d565b5092915050565b600080805b838110156101915760008054600181810183559180527f290decd9" - + "548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56301829055918201910161019d565b600" - + "260209081526000928352604080842090915290825290205481565b60015481565b60038054600101905561" - + "0216610205565b565b60006102238261022e565b600181905592915050565b600061023c6002830361022e5" - + "65b6102486001840361022e565b01929150505600a165627a7a72305820bc44fd5f3a0e48cc057752b52e3a" - + "bf50cd7dc75b3874ea7d049893cf1a2e345f0029"; - abi = "[{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"" - + "iarray\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"" - + "stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{" - + "\"name\":\"a\",\"type\":\"uint256\"}],\"name\":\"testUseCpu\",\"outputs\":[{\"name\":" - + "\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"" - + "type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"a\",\"type\":\"" - + "uint256\"}],\"name\":\"testUseStorage\",\"outputs\":[{\"name\":\"\",\"type\":\"" - + "uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function" - + "\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\"," - + "\"type\":\"address\"}],\"name\":\"m\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"" - + "}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\"" - + ":true,\"inputs\":[],\"name\":\"calculatedFibNumber\",\"outputs\":[{\"name\":\"\",\"type" - + "\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}," - + "{\"constant\":false,\"inputs\":[],\"name\":\"test\",\"outputs\":[],\"payable\":false," - + "\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs" - + "\":[{\"name\":\"n\",\"type\":\"uint256\"}],\"name\":\"setFibonacci\",\"outputs\":" - + "[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"" - + "nonpayable\",\"type\":\"function\"}]"; AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(linkage005Address, blockingStubFull); Account info; @@ -149,6 +115,14 @@ public void testEnergyCostDetail() { logger.info("beforeNetLimit:" + beforeNetLimit); logger.info("beforeNetUsed:" + beforeNetUsed); logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); + + String filePath = "./src/test/resources/soliditycode/contractLinkage005.sol"; + String contractName = "timeoutTest"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + String txid = PublicMethed.deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, linkage005Key, linkage005Address, blockingStubFull); @@ -157,6 +131,8 @@ public void testEnergyCostDetail() { Optional infoById = null; infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + Account infoafter = PublicMethed.queryAccount(linkage005Address, blockingStubFull1); AccountResourceMessage resourceInfoafter = PublicMethed.getAccountResource(linkage005Address, blockingStubFull1); diff --git a/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage006.java b/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage006.java index ab73f71f639..60c40eaeee0 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage006.java +++ b/src/test/java/stest/tron/wallet/dailybuild/manual/ContractLinkage006.java @@ -2,6 +2,7 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -91,31 +92,6 @@ public void teststackOutByContract() { Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(linkage006Address, 1000000L, 0, 1, linkage006Key, blockingStubFull)); PublicMethed.waitProduceNextBlock(blockingStubFull); - contractName = "stackOutByContract"; - code = "60806040526000805561026c806100176000396000f3006080604052600436106100565763ffffffff7c01" - + "0000000000000000000000000000000000000000000000000000000060003504166306661abd811461005b5" - + "780631548567714610082578063399ae724146100a8575b600080fd5b34801561006757600080fd5b506100" - + "706100cc565b60408051918252519081900360200190f35b6100a673fffffffffffffffffffffffffffffff" - + "fffffffff600435166024356100d2565b005b6100a673ffffffffffffffffffffffffffffffffffffffff60" - + "0435166024356101af565b60005481565b80600054101561017257600080546001018155604080517f15485" - + "67700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffff" - + "ffffffffffffffffff851660048201526024810184905290513092631548567792604480820193918290030" - + "1818387803b15801561015557600080fd5b505af1158015610169573d6000803e3d6000fd5b505050506100" - + "d2565b8060005414156101ab5760405173ffffffffffffffffffffffffffffffffffffffff8316906000906" - + "0149082818181858883f150505050505b5050565b6000808055604080517f15485677000000000000000000" - + "00000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851" - + "6600482015260248101849052905130926315485677926044808201939182900301818387803b1580156102" - + "2457600080fd5b505af1158015610238573d6000803e3d6000fd5b5050505050505600a165627a7a7230582" - + "0ecdc49ccf0dea5969829debf8845e77be6334f348e9dcaeabf7e98f2d6c7f5270029"; - abi = "[{\"constant\":true,\"inputs\":[],\"name\":\"count\",\"outputs\":[{\"name\":\"\",\"type" - + "\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}," - + "{\"constant\":false,\"inputs\":[{\"name\":\"addr\",\"type\":\"address\"},{\"name\":\"" - + "max\",\"type\":\"uint256\"}],\"name\":\"hack\",\"outputs\":[],\"payable\":true,\"" - + "stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{" - + "\"name\":\"addr\",\"type\":\"address\"},{\"name\":\"max\",\"type\":\"uint256\"}],\"" - + "name\":\"init\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type" - + "\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type" - + "\":\"constructor\"}]"; AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(linkage006Address, blockingStubFull); Account info; @@ -134,6 +110,14 @@ public void teststackOutByContract() { logger.info("beforeNetLimit:" + beforeNetLimit); logger.info("beforeNetUsed:" + beforeNetUsed); logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); + + String filePath = "./src/test/resources/soliditycode/contractLinkage006.sol"; + String contractName = "AA"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + //success ,balnace change.use EnergyUsed and NetUsed txid = PublicMethed.deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 1000L, 100, null, linkage006Key, @@ -141,6 +125,7 @@ public void teststackOutByContract() { PublicMethed.waitProduceNextBlock(blockingStubFull); infoById = PublicMethed .getTransactionInfoById(txid, blockingStubFull); + logger.info("txid is " + txid); contractAddress = infoById.get().getContractAddress().toByteArray(); Long energyUsageTotal = infoById.get().getReceipt().getEnergyUsageTotal(); Long fee = infoById.get().getFee(); @@ -177,7 +162,7 @@ public void teststackOutByContract() { Assert.assertTrue((beforeNetUsed + netUsed) >= afterNetUsed); Assert.assertTrue((beforeEnergyUsed + energyUsed) >= afterEnergyUsed); PublicMethed.unFreezeBalance(linkage006Address, linkage006Key, 1, - linkage006Address, blockingStubFull); + null, blockingStubFull); } @Test(enabled = true, description = "Boundary value for contract stack(63 is the largest level)") @@ -215,6 +200,7 @@ public void teststackOutByContract1() { "init(address,uint256)", initParmes, false, 0, 100000000L, linkage006Address2, linkage006Key2, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); Optional infoById1 = PublicMethed .getTransactionInfoById(txid, blockingStubFull); diff --git a/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario002.java b/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario002.java index 7085cb1bd7b..b5834aebb38 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario002.java +++ b/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario002.java @@ -2,6 +2,7 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -74,7 +75,7 @@ public void deployTronNative() { byte[] contract002Address = ecKey1.getAddress(); String contract002Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); - Assert.assertTrue(PublicMethed.sendcoin(contract002Address, 50000000L, fromAddress, + Assert.assertTrue(PublicMethed.sendcoin(contract002Address, 500000000L, fromAddress, testKey002, blockingStubFull)); PublicMethed.waitProduceNextBlock(blockingStubFull); Assert.assertTrue(PublicMethed.freezeBalanceGetEnergy(contract002Address, 1000000L, @@ -90,77 +91,12 @@ public void deployTronNative() { logger.info("before energy usage is " + Long.toString(energyUsage)); logger.info("before balance is " + Long.toString(balanceBefore)); - String contractName = "tronNative"; - String code = "608060405260008054600160a060020a03199081166201000117909155600180548216620100021" - + "790556002805482166201000317905560038054821662010004179055600480548216620100051790556005" - + "8054821662010006179055600680549091166201000717905534801561007757600080fd5b506104ce80610" - + "0876000396000f3006080604052600436106100da5763ffffffff7c01000000000000000000000000000000" - + "000000000000000000000000006000350416630a90265081146100df5780630dfb51ac146100fc57806345b" - + "d20101461012d5780634efaaa1b1461014257806352ae1b811461016657806353c4263f1461017b5780635f" - + "d8c710146101905780637c369c90146101a55780637f2b7f93146101ba5780638259d5531461020f5780639" - + "06fbec914610227578063961a8be71461023c578063cee14bb414610251578063ec9928bd14610275578063" - + "fb4f32aa14610292575b600080fd5b3480156100eb57600080fd5b506100fa6004356024356102a7565b005" - + "b34801561010857600080fd5b506101116102dc565b60408051600160a060020a0390921682525190819003" - + "60200190f35b34801561013957600080fd5b506101116102eb565b34801561014e57600080fd5b506100fa6" - + "00160a060020a03600435166024356102fa565b34801561017257600080fd5b50610111610320565b348015" - + "61018757600080fd5b5061011161032f565b34801561019c57600080fd5b506100fa61033e565b348015610" - + "1b157600080fd5b5061011161035d565b3480156101c657600080fd5b506040805160206004803580820135" - + "83810280860185019096528085526100fa95369593946024949385019291829185019084908082843750949" - + "75061036c9650505050505050565b34801561021b57600080fd5b506100fa6004356103c6565b3480156102" - + "3357600080fd5b506101116103f7565b34801561024857600080fd5b50610111610406565b34801561025d5" - + "7600080fd5b506100fa600160a060020a0360043516602435610415565b34801561028157600080fd5b5061" - + "00fa600435602435151561044d565b34801561029e57600080fd5b506100fa610483565b600154604080518" - + "48152602081018490528151600160a060020a0390931692818301926000928290030181855af45050505050" - + "565b600654600160a060020a031681565b600354600160a060020a031681565b816080528060a0526000608" - + "060406080620100016000f4151561031c57600080fd5b5050565b600254600160a060020a031681565b6004" - + "54600160a060020a031681565b600354604051600160a060020a03909116906000818181855af4505050565" - + "b600554600160a060020a031681565b6005546040518251600160a060020a03909216918391908190602080" - + "8501910280838360005b838110156103aa578181015183820152602001610392565b5050505090500191505" - + "0600060405180830381855af450505050565b600654604080518381529051600160a060020a039092169160" - + "208083019260009291908290030181855af450505050565b600054600160a060020a031681565b600154600" - + "160a060020a031681565b6000805460408051600160a060020a038681168252602082018690528251931693" - + "81830193909290918290030181855af45050505050565b60045460408051848152831515602082015281516" - + "00160a060020a0390931692818301926000928290030181855af45050505050565b600254604051600160a0" - + "60020a03909116906000818181855af45050505600a165627a7a7230582076efe233a097282a46d3aefb879" - + "b720ed02a4ad3c6cf053cc5936a01e366c7dc0029"; - String abi = "[{\"constant\":false,\"inputs\":[{\"name\":\"frozen_Balance\",\"type\":\"uint256" - + "\"},{\"name\":\"frozen_Duration\",\"type\":\"uint256\"}],\"name\":\"freezeBalance\",\"o" - + "utputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}" - + ",{\"constant\":true,\"inputs\":[],\"name\":\"deleteProposalAddress\",\"outputs\":[{\"na" - + "me\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type" - + "\"" - + ":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"withdrawBalanceAddress\",\"o" - + "utputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\"" - + ":\"" - + "view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"witnessAddr\"" - + ",\"type\":\"address\"},{\"name\":\"voteValue\",\"type\":\"uint256\"}],\"name\":\"voteUs" - + "ingAssembly\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"typ" - + "e\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"unFreezeBalanceAddress\"" - + ",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability" - + "\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"approveP" - + "roposalAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false," - + "\"" - + "stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"n" - + "ame\":\"withdrawBalance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpay" - + "able\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"createProposa" - + "lAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"state" - + "Mutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":" - + "\"data\",\"type\":\"bytes32[]\"}],\"name\":\"createProposal\",\"outputs\":[],\"payable" - + "\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false," - + "\"inputs\":[{\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"deleteProposal\",\"outpu" - + "ts\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"" - + "constant\":true,\"inputs\":[],\"name\":\"voteContractAddress\",\"outputs\":[{\"name\":" - + "\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"" - + "function\"},{\"constant\":true,\"inputs\":[],\"name\":\"freezeBalanceAddress\",\"output" - + "s\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view" - + "\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"witnessAddr\",\"" - + "type\":\"address\"},{\"name\":\"voteValue\",\"type\":\"uint256\"}],\"name\":\"voteForS" - + "ingleWitness\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"t" - + "ype\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"id\",\"type\":\"uint25" - + "6\"},{\"name\":\"isApprove\",\"type\":\"bool\"}],\"name\":\"approveProposal\",\"output" - + "s\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"" - + "constant\":false,\"inputs\":[],\"name\":\"unFreezeBalance\",\"outputs\":[],\"payable\"" - + ":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"; + String contractName = "TronNative"; + String filePath = "./src/test/resources/soliditycode/contractScenario002.sol"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); String txid = PublicMethed.deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contract002Key, contract002Address, blockingStubFull); diff --git a/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario011.java b/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario011.java index 052aeaca51b..d2e592db67e 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario011.java +++ b/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario011.java @@ -2,6 +2,7 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -113,10 +114,11 @@ public void deployErc721KittyCore() { logger.info("before cpu limit is " + Long.toString(cpuLimit)); logger.info("before cpu usage is " + Long.toString(cpuUsage)); String contractName = "KittyCore"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractScenario011_deployErc721KittyCore"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractScenario011_deployErc721KittyCore"); + String filePath = "./src/test/resources/soliditycode/contractScenario011.sol"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); logger.info("Kitty Core"); kittyCoreContractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, consumeUserResourcePercent, null, deployKey, @@ -154,15 +156,23 @@ public void deploySaleClockAuction() { logger.info("before cpu limit is " + Long.toString(cpuLimit)); logger.info("before cpu usage is " + Long.toString(cpuUsage)); String contractName = "SaleClockAuction"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractScenario011_deploySaleClockAuction") - + kittyCoreAddressAndCut; - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractScenario011_deploySaleClockAuction"); + String filePath = "./src/test/resources/soliditycode/contractScenario011.sol"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); logger.info("Sale Clock Auction"); - saleClockAuctionContractAddress = PublicMethed.deployContract(contractName, abi, code, - "", maxFeeLimit, 0L, consumeUserResourcePercent, null, deployKey, - deployAddress, blockingStubFull); + //saleClockAuctionContractAddress; + String data = "\"" + Base58.encode58Check(kittyCoreContractAddress) + "\"," + 100; + String deplTxid = PublicMethed + .deployContractWithConstantParame(contractName, abi, code, "constructor(address,uint256)", + data, "", maxFeeLimit, 0L, consumeUserResourcePercent, null, deployKey, deployAddress, + blockingStubFull); + Optional info = PublicMethed + .getTransactionInfoById(deplTxid, blockingStubFull); + Assert.assertTrue(info.get().getResultValue() == 0); + + saleClockAuctionContractAddress = info.get().getContractAddress().toByteArray(); PublicMethed.waitProduceNextBlock(blockingStubFull); SmartContract smartContract = PublicMethed.getContract(saleClockAuctionContractAddress, blockingStubFull); @@ -175,6 +185,14 @@ public void deploySaleClockAuction() { logger.info("after balance is " + Long.toString(account.getBalance())); logger.info("after cpu limit is " + Long.toString(cpuLimit)); logger.info("after cpu usage is " + Long.toString(cpuUsage)); + + String triggerTxid = PublicMethed + .triggerContract(saleClockAuctionContractAddress, "isSaleClockAuction()", "#", false, 0, + maxFeeLimit, deployAddress, deployKey, blockingStubFull); + Optional inFoByid = PublicMethed + .getTransactionInfoById(triggerTxid, blockingStubFull); + logger.info("Ttttt " + triggerTxid); + Assert.assertTrue(inFoByid.get().getResultValue() == 0); } @Test(enabled = true, description = "Deploy Erc721 contract \"Siring Clock Auction\"") @@ -188,16 +206,22 @@ public void deploySiringClockAuction() { logger.info("before cpu limit is " + Long.toString(cpuLimit)); logger.info("before cpu usage is " + Long.toString(cpuUsage)); String contractName = "SiringClockAuction"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractScenario011_deploySiringClockAuction") - + kittyCoreAddressAndCut; - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractScenario011_deploySiringClockAuction"); - logger.info("Siring Clock Auction"); - siringClockAuctionContractAddress = PublicMethed.deployContract(contractName, abi, code, - "", maxFeeLimit, 0L, consumeUserResourcePercent, null, deployKey, - deployAddress, blockingStubFull); + String filePath = "./src/test/resources/soliditycode/contractScenario011.sol"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + String data = "\"" + Base58.encode58Check(kittyCoreContractAddress) + "\"," + 100; + String siringClockAuctionContractAddressTxid = PublicMethed + .deployContractWithConstantParame(contractName, abi, code, "constructor(address,uint256)", + data, + "", maxFeeLimit, 0L, consumeUserResourcePercent, null, deployKey, + deployAddress, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); + Optional info2 = PublicMethed + .getTransactionInfoById(siringClockAuctionContractAddressTxid, blockingStubFull); + siringClockAuctionContractAddress = info2.get().getContractAddress().toByteArray(); + Assert.assertTrue(info2.get().getResultValue() == 0); SmartContract smartContract = PublicMethed.getContract(siringClockAuctionContractAddress, blockingStubFull); Assert.assertFalse(StringUtils.isEmpty(smartContract.getBytecode())); @@ -222,16 +246,21 @@ public void deployGeneScienceInterface() { logger.info("before cpu limit is " + Long.toString(cpuLimit)); logger.info("before cpu usage is " + Long.toString(cpuUsage)); String contractName = "GeneScienceInterface"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractScenario011_deployGeneScienceInterface") - + kittyCoreAddressAndCut; - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractScenario011_deployGeneScienceInterface"); - logger.info("gene Science Interface"); - geneScienceInterfaceContractAddress = PublicMethed.deployContract(contractName, abi, code, + String filePath = "./src/test/resources/soliditycode/contractScenario011.sol"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + + String txid = PublicMethed.deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 0L, consumeUserResourcePercent, null, deployKey, deployAddress, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); + Optional info2 = PublicMethed + .getTransactionInfoById(txid, blockingStubFull); + geneScienceInterfaceContractAddress = info2.get().getContractAddress().toByteArray(); + Assert.assertTrue(info2.get().getResultValue() == 0); + SmartContract smartContract = PublicMethed.getContract(geneScienceInterfaceContractAddress, blockingStubFull); Assert.assertFalse(StringUtils.isEmpty(smartContract.getBytecode())); diff --git a/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario014.java b/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario014.java index 14b007c5945..0d76db4dcf3 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario014.java +++ b/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario014.java @@ -2,6 +2,7 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -46,6 +47,7 @@ public class ContractScenario014 { ECKey ecKey1 = new ECKey(Utils.getRandom()); byte[] contract014Address = ecKey1.getAddress(); String contract014Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); + String priKey014 = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); ECKey ecKey2 = new ECKey(Utils.getRandom()); byte[] receiverAddress = ecKey2.getAddress(); @@ -71,9 +73,6 @@ public void beforeClass() { @Test(enabled = true, description = "Triple trigger in smart contract") public void testTripleTrigger() { - ecKey1 = new ECKey(Utils.getRandom()); - contract014Address = ecKey1.getAddress(); - contract014Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); ecKey2 = new ECKey(Utils.getRandom()); receiverAddress = ecKey2.getAddress(); @@ -81,14 +80,20 @@ public void testTripleTrigger() { PublicMethed.printAddress(contract014Key); PublicMethed.printAddress(receiverKey); - Assert.assertTrue(PublicMethed.sendcoin(contract014Address, 5000000000L, fromAddress, + Assert.assertTrue(PublicMethed.sendcoin(contract014Address, 5000000000000L, fromAddress, testKey002, blockingStubFull)); + Assert.assertTrue(PublicMethed + .freezeBalanceGetEnergy(contract014Address, 1000000000000L, 0, 1, priKey014, + blockingStubFull)); + + logger.info("contract014Address : == " + contract014Key); //Deploy contract1, contract1 has a function to transaction 5 sun to target account String contractName = "Contract1"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractScenario014_testTripleTrigger"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractScenario014_testTripleTrigger"); + String filePath = "./src/test/resources/soliditycode/contractScenario014.sol"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); txid = PublicMethed.deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, contract014Key, contract014Address, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); @@ -99,12 +104,13 @@ public void testTripleTrigger() { //Deploy contract2, contract2 has a function to call contract1 transaction sun function. // and has a revert function. - String code1 = Configuration.getByPath("testng.conf") - .getString("code.code1_ContractScenario014_testTripleTrigger"); - String abi1 = Configuration.getByPath("testng.conf") - .getString("abi.abi1_ContractScenario014_testTripleTrigger"); + contractName = "contract2"; + String filePath1 = "./src/test/resources/soliditycode/contractScenario014.sol"; + HashMap retMap1 = PublicMethed.getBycodeAbi(filePath1, contractName); + + String code1 = retMap1.get("byteCode").toString(); + String abi1 = retMap1.get("abI").toString(); String parame = "\"" + Base58.encode58Check(contractAddress1) + "\""; - contractName = "Contract2"; txid = PublicMethed.deployContractWithConstantParame(contractName, abi1, code1, "constructor(address)", parame, "", maxFeeLimit, 0L, 100, null, @@ -114,12 +120,13 @@ public void testTripleTrigger() { contractAddress2 = infoById.get().getContractAddress().toByteArray(); //Deploy contract3, trigger contrct2 function. - String code2 = Configuration.getByPath("testng.conf") - .getString("code.code2_ContractScenario014_testTripleTrigger"); - String abi2 = Configuration.getByPath("testng.conf") - .getString("abi.abi2_ContractScenario014_testTripleTrigger"); + contractName = "contract3"; + String filePath2 = "./src/test/resources/soliditycode/contractScenario014.sol"; + HashMap retMap2 = PublicMethed.getBycodeAbi(filePath2, contractName); + + String code2 = retMap2.get("byteCode").toString(); + String abi2 = retMap2.get("abI").toString(); parame = "\"" + Base58.encode58Check(contractAddress2) + "\""; - contractName = "Contract3"; txid = PublicMethed.deployContractWithConstantParame(contractName, abi2, code2, "constructor(address)", parame, "", maxFeeLimit, 0L, 100, null, @@ -150,12 +157,13 @@ public void testTripleTrigger() { String receiveAddress = "\"" + Base58.encode58Check(receiverAddress) + "\""; txid = PublicMethed.triggerContract(contractAddress2, "triggerContract1(address)", receiveAddress, false, - 0, 10000000L, contract014Address, contract014Key, blockingStubFull); + 0, maxFeeLimit, contract014Address, contract014Key, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); Assert.assertTrue(infoById.get().getResultValue() == 0); contract2AccountInfo = PublicMethed.queryAccount(contractAddress2, blockingStubFull); final Long contract2AfterBalance = contract2AccountInfo.getBalance(); + //contract2AccountInfo.getAccountResource().getFrozenBalanceForEnergy(); receiverAccountInfo = PublicMethed.queryAccount(receiverAddress, blockingStubFull); Long receiverAfterBalance = receiverAccountInfo.getBalance(); contract1AccountInfo = PublicMethed.queryAccount(contractAddress1, blockingStubFull); diff --git a/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario015.java b/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario015.java new file mode 100644 index 00000000000..a8a4fcfe35b --- /dev/null +++ b/src/test/java/stest/tron/wallet/dailybuild/manual/ContractScenario015.java @@ -0,0 +1,140 @@ +package stest.tron.wallet.dailybuild.manual; + +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import java.util.Optional; +import java.util.concurrent.TimeUnit; +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeSuite; +import org.testng.annotations.Test; +import org.tron.api.WalletGrpc; +import org.tron.common.crypto.ECKey; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.Utils; +import org.tron.core.Wallet; +import org.tron.protos.Protocol.Account; +import org.tron.protos.Protocol.TransactionInfo; +import stest.tron.wallet.common.client.Configuration; +import stest.tron.wallet.common.client.Parameter.CommonConstant; +import stest.tron.wallet.common.client.utils.Base58; +import stest.tron.wallet.common.client.utils.PublicMethed; + +@Slf4j +public class ContractScenario015 { + + private final String testKey002 = Configuration.getByPath("testng.conf") + .getString("foundationAccount.key1"); + private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); + + private ManagedChannel channelFull = null; + private WalletGrpc.WalletBlockingStub blockingStubFull = null; + private String fullnode = Configuration.getByPath("testng.conf") + .getStringList("fullnode.ip.list").get(0); + private Long maxFeeLimit = Configuration.getByPath("testng.conf") + .getLong("defaultParameter.maxFeeLimit"); + + byte[] contractAddress1 = null; + byte[] contractAddress2 = null; + byte[] contractAddress3 = null; + String txid = ""; + Optional infoById = null; + String contractName = ""; + + ECKey ecKey1 = new ECKey(Utils.getRandom()); + byte[] contract014Address = ecKey1.getAddress(); + String contract014Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); + + ECKey ecKey2 = new ECKey(Utils.getRandom()); + byte[] receiverAddress = ecKey2.getAddress(); + String receiverKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); + + @BeforeSuite + public void beforeSuite() { + Wallet wallet = new Wallet(); + Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); + } + + /** + * constructor. + */ + + @BeforeClass(enabled = true) + public void beforeClass() { + channelFull = ManagedChannelBuilder.forTarget(fullnode) + .usePlaintext(true) + .build(); + blockingStubFull = WalletGrpc.newBlockingStub(channelFull); + } + + @Test(enabled = true, description = "TRON TRC20 transfer token") + public void trc20Tron() { + ecKey1 = new ECKey(Utils.getRandom()); + contract014Address = ecKey1.getAddress(); + contract014Key = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); + + ecKey2 = new ECKey(Utils.getRandom()); + receiverAddress = ecKey2.getAddress(); + receiverKey = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); + PublicMethed.printAddress(contract014Key); + PublicMethed.printAddress(receiverKey); + + Assert.assertTrue(PublicMethed.sendcoin(contract014Address, 500000000L, fromAddress, + testKey002, blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + //Deploy contract1, contract1 has a function to transaction 5 sun to target account + String contractName = "TRON TRC20"; + String code = Configuration.getByPath("testng.conf") + .getString("code.code_Scenario015_TRC20_TRON"); + String abi = Configuration.getByPath("testng.conf") + .getString("abi.abi_Scenario015_TRC20_TRON"); + txid = PublicMethed.deployContractAndGetTransactionInfoById(contractName, abi, code, "", + maxFeeLimit, 0L, 100, null, contract014Key, contract014Address, blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + logger.info(txid); + infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); + Assert.assertTrue(infoById.get().getResultValue() == 0); + contractAddress1 = infoById.get().getContractAddress().toByteArray(); + //Set SiringAuctionAddress to kitty core. + String siringContractString = "\"" + Base58.encode58Check(fromAddress) + "\""; + txid = PublicMethed + .triggerContract(contractAddress1, "balanceOf(address)", siringContractString, + false, 0, 10000000L, contract014Address, contract014Key, blockingStubFull); + logger.info(txid); + + siringContractString = "\"" + Base58.encode58Check(fromAddress) + "\",\"" + 17 + "\""; + txid = PublicMethed.triggerContract(contractAddress1,"transfer(address,uint256)", + siringContractString,false, 0, 10000000L, contract014Address, + contract014Key, blockingStubFull); + + PublicMethed.waitProduceNextBlock(blockingStubFull); + Optional infoById = null; + + infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); + Assert.assertTrue(infoById.get().getResultValue() == 0); + + siringContractString = "\"" + Base58.encode58Check(fromAddress) + "\""; + txid = PublicMethed + .triggerContract(contractAddress1, "balanceOf(address)", + siringContractString, false, 0, 10000000L, contract014Address, + contract014Key, blockingStubFull); + logger.info(txid); + } + + + /** + * constructor. + */ + + @AfterClass + public void shutdown() throws InterruptedException { + if (channelFull != null) { + channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); + } + } +} + + diff --git a/src/test/java/stest/tron/wallet/dailybuild/manual/ContractUnknownException.java b/src/test/java/stest/tron/wallet/dailybuild/manual/ContractUnknownException.java index 68288137540..f16cc9c45e5 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/manual/ContractUnknownException.java +++ b/src/test/java/stest/tron/wallet/dailybuild/manual/ContractUnknownException.java @@ -4,6 +4,7 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -109,16 +110,11 @@ public void testGrammar001() { logger.info("beforeNetUsed:" + beforeNetUsed); logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); logger.info("beforeenergyLimit:" + beforeenergyLimit); + String filePath = "src/test/resources/soliditycode/contractUnknownException.sol"; String contractName = "testA"; - String code = "60806040526000600a600e609f565b6040518091039082f0801580156028573d600080" - + "3e3d6000fd5b509050905080600160a060020a031663946644cd6040518163ffffffff167c0100" - + "000000000000000000000000000000000000000000000000000000028152600401600060405180" - + "830381600087803b158015608357600080fd5b505af11580156096573d6000803e3d6000fd5b50" - + "5050505060ad565b60405160088060ef83390190565b60358060ba6000396000f3006080604052" - + "600080fd00a165627a7a723058205f699e7434a691ee9a433c497973f2eee624efde40e7b7dd86" - + "512767fbe7752c0029608060405233ff00"; - String abi = "[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\"," - + "\"type\":\"constructor\"}]"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); String txid = PublicMethed .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 20L, 100, null, testKeyForGrammarAddress, @@ -172,17 +168,11 @@ public void testGrammar002() { logger.info("beforeNetUsed:" + beforeNetUsed); logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); logger.info("beforeenergyLimit:" + beforeenergyLimit); + String filePath = "src/test/resources/soliditycode/contractUnknownException.sol"; String contractName = "testB"; - String code = "60806040526000600a600e609f565b6040518091039082f080158015602" - + "8573d6000803e3d6000fd5b509050905080600160a060020a031663946644cd6040" - + "518163ffffffff167c0100000000000000000000000000000000000000000000000" - + "000000000028152600401600060405180830381600087803b158015608357600080" - + "fd5b505af11580156096573d6000803e3d6000fd5b505050505060ae565b6040516" - + "00a806100f183390190565b6035806100bc6000396000f3006080604052600080fd" - + "00a165627a7a7230582036a40a807cbf71508011574ef42c706ad7b40d844807909" - + "c3b8630f9fb9ae6f700296080604052600080fd00"; - String abi = "[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"" - + "nonpayable\",\"type\":\"constructor\"}]"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); String txid = PublicMethed .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 20L, 100, null, testKeyForGrammarAddress2, @@ -241,16 +231,11 @@ public void testGrammar003() { logger.info("beforeNetUsed:" + beforeNetUsed); logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); logger.info("beforeenergyLimit:" + beforeenergyLimit); + String filePath = "src/test/resources/soliditycode/contractUnknownException.sol"; String contractName = "testC"; - String code = "60806040526000600a600e609f565b6040518091039082f0801580156028573d600" - + "0803e3d6000fd5b509050905080600160a060020a031663946644cd6040518163ffffffff16" - + "7c0100000000000000000000000000000000000000000000000000000000028152600401600" - + "060405180830381600087803b158015608357600080fd5b505af11580156096573d6000803e" - + "3d6000fd5b505050505060ad565b60405160078060ef83390190565b60358060ba600039600" - + "0f3006080604052600080fd00a165627a7a72305820970ee7543687d338b72131a122af927a" - + "698a081c0118577f49fffd8831a1195800296080604052fe00"; - String abi = "[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\"," - + "\"type\":\"constructor\"}]"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); String txid = PublicMethed .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 20L, 100, null, testKeyForGrammarAddress3, @@ -308,16 +293,11 @@ public void testGrammar004() { logger.info("beforeNetUsed:" + beforeNetUsed); logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); logger.info("beforeenergyLimit:" + beforeenergyLimit); + String filePath = "src/test/resources/soliditycode/contractUnknownException.sol"; String contractName = "testD"; - String code = "60806040526000600a600e609f565b6040518091039082f0801580156028573d" - + "6000803e3d6000fd5b509050905080600160a060020a031663946644cd6040518163fffff" - + "fff167c010000000000000000000000000000000000000000000000000000000002815260" - + "0401600060405180830381600087803b158015608357600080fd5b505af11580156096573" - + "d6000803e3d6000fd5b505050505060ae565b604051600a806100f183390190565b603580" - + "6100bc6000396000f3006080604052600080fd00a165627a7a72305820fd7ca23ea399b6d" - + "513a8d4eb084f5eb748b94fab6437bfb5ea9f4a03d9715c3400296080604052600080fd00"; - String abi = "[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\"" - + ",\"type\":\"constructor\"}]"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); String txid = PublicMethed .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 20L, 100, null, testKeyForGrammarAddress4, diff --git a/src/test/java/stest/tron/wallet/dailybuild/manual/RequireException.java b/src/test/java/stest/tron/wallet/dailybuild/manual/RequireException.java index d330bac53f8..58e811ca094 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/manual/RequireException.java +++ b/src/test/java/stest/tron/wallet/dailybuild/manual/RequireException.java @@ -2,6 +2,7 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; @@ -99,20 +100,12 @@ public void test1TestRequireContract() { .sendcoin(asset016Address, 1000000000L, testNetAccountAddress, testNetAccountKey, blockingStubFull)); - String contractName = "TestRequireContract"; - String code = "608060405234801561001057600080fd5b5060b58061001f6000396000f30060806040526004361" - + "0605c5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416" - + "632b813bc081146061578063357815c414607557806350bff6bf146075578063a26388bb146075575b60008" - + "0fd5b348015606c57600080fd5b5060736087565b005b348015608057600080fd5b506073605c565bfe00a1" - + "65627a7a723058209284d2c51e121903dde36db88dae131b1b20dc83b987a6f491dcac2d9b2d30db0029"; - String abi = "[{\"constant\":false,\"inputs\":[],\"name\":\"testAssert\",\"outputs\":[],\"" - + "payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant" - + "\":false,\"inputs\":[],\"name\":\"testRequire\",\"outputs\":[],\"payable\":false,\"" - + "stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs" - + "\":[],\"name\":\"testThrow\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"" - + "nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"" - + "testRevert\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"" - + "type\":\"function\"}]"; + String filePath = + "src/test/resources/soliditycode/requireExceptiontest1TestRequireContract.sol"; + String contractName = "TestThrowsContract"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, testKeyForAssetIssue016, asset016Address, blockingStubFull); @@ -173,20 +166,12 @@ public void test1TestRequireContract() { @Test(enabled = true, description = "Throw Exception") public void test2TestThrowsContract() { + String filePath = + "src/test/resources/soliditycode/requireExceptiontest2TestThrowsContract.sol"; String contractName = "TestThrowsContract"; - String code = "608060405234801561001057600080fd5b5060b58061001f6000396000f30060806040526004361" - + "0605c5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416" - + "632b813bc081146061578063357815c414607557806350bff6bf146075578063a26388bb146075575b60008" - + "0fd5b348015606c57600080fd5b5060736087565b005b348015608057600080fd5b506073605c565bfe00a1" - + "65627a7a723058209284d2c51e121903dde36db88dae131b1b20dc83b987a6f491dcac2d9b2d30db0029"; - String abi = "[{\"constant\":false,\"inputs\":[],\"name\":\"testAssert\",\"outputs\":[],\"" - + "payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant" - + "\":false,\"inputs\":[],\"name\":\"testRequire\",\"outputs\":[],\"payable\":false,\"" - + "stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs" - + "\":[],\"name\":\"testThrow\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"" - + "nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"" - + "testRevert\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\"," - + "\"type\":\"function\"}]"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, testKeyForAssetIssue016, asset016Address, blockingStubFull); @@ -247,21 +232,12 @@ public void test2TestThrowsContract() { @Test(enabled = true, description = "Call Revert ") public void test3TestRevertContract() { + String filePath = + "src/test/resources/soliditycode/requireExceptiontest3TestRevertContract.sol"; String contractName = "TestThrowsContract"; - String code = "608060405234801561001057600080fd5b5060b58061001f6000396000f3006080604052600436" - + "10605c5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504" - + "16632b813bc081146061578063357815c414607557806350bff6bf146075578063a26388bb146075575b60" - + "0080fd5b348015606c57600080fd5b5060736087565b005b348015608057600080fd5b506073605c565bfe" - + "00a165627a7a723058209284d2c51e121903dde36db88dae131b1b20dc83b987a6f491dcac2d9b2d30db0" - + "029"; - String abi = "[{\"constant\":false,\"inputs\":[],\"name\":\"testAssert\",\"outputs\":[],\"" - + "payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant" - + "\":false,\"inputs\":[],\"name\":\"testRequire\",\"outputs\":[],\"payable\":false,\"" - + "stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\"" - + ":[],\"name\":\"testThrow\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"" - + "nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"" - + "testRevert\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\"," - + "\"type\":\"function\"}]"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, testKeyForAssetIssue016, asset016Address, blockingStubFull); @@ -320,17 +296,14 @@ public void test3TestRevertContract() { } - @Test(enabled = true, description = "No payable function call value") + @Test(enabled = false, description = "No payable function call value") public void test4noPayableContract() { + String filePath = + "src/test/resources/soliditycode/requireExceptiontest4noPayableContract_1.sol"; String contractName = "noPayableContract"; - String code = "6080604052348015600f57600080fd5b5060978061001e6000396000f3006080604052600436106" - + "03e5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663" - + "2380bf0581146043575b600080fd5b348015604e57600080fd5b5060556067565b604080519182525190819" - + "00360200190f35b34905600a165627a7a72305820c15441923f769bff9193db8304db516b768651d3eb0861" - + "a38163b3e7e6174ee50029"; - String abi = "[{\"constant\":false,\"inputs\":[],\"name\":\"noPayable\",\"outputs\":[{\"name" - + "\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\"," - + "\"type\":\"function\"}]"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, testKeyForAssetIssue016, asset016Address, blockingStubFull); @@ -388,7 +361,7 @@ public void test4noPayableContract() { } - @Test(enabled = true, description = "No payable Constructor") + @Test(enabled = false, description = "No payable Constructor") public void test5noPayableConstructor() { Account info; @@ -404,12 +377,12 @@ public void test5noPayableConstructor() { logger.info("beforeEnergyUsed:" + beforeEnergyUsed); logger.info("beforeNetUsed:" + beforeNetUsed); logger.info("beforeFreeNetUsed:" + beforeFreeNetUsed); - String contractName = "noPayableConstructor"; - String code = "6080604052348015600f57600080fd5b506040516020806071833981016040525134811115602c5" - + "7600080fd5b600055603580603c6000396000f3006080604052600080fd00a165627a7a72305820cb20f649" - + "31c41844749c1571bfc4dfdd268a58ed29b7446dd817ce3c54b014150029"; - String abi = "[{\"inputs\":[{\"name\":\"_money\",\"type\":\"uint256\"}],\"payable\":false,\"" - + "stateMutability\":\"nonpayable\",\"type\":\"constructor\"}]"; + String filePath = + "src/test/resources/soliditycode/requireExceptiontest5noPayableConstructor_1.sol"; + String contractName = "MyContract"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); final String txid = PublicMethed .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 22L, 100, null, @@ -451,16 +424,12 @@ public void test5noPayableConstructor() { @Test(enabled = true, description = "Transfer failed") public void test6transferTestContract() { + String filePath = + "src/test/resources/soliditycode/requireExceptiontest6transferTestContract.sol"; String contractName = "transferTestContract"; - String code = "608060405234801561001057600080fd5b5060d28061001f6000396000f30060806040526004361" - + "0603e5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416" - + "6319b357c581146043575b600080fd5b606273ffffffffffffffffffffffffffffffffffffffff600435166" - + "064565b005b60405173ffffffffffffffffffffffffffffffffffffffff821690600090600a908281818185" - + "8883f1935050505015801560a2573d6000803e3d6000fd5b50505600a165627a7a7230582078c54bf20a44a" - + "5fecf3e03a7e6daf7b712dc71db7ec24840549f1655c55123760029"; - String abi = "[{\"constant\":false,\"inputs\":[{\"name\":\"addr\",\"type\":\"address\"}],\"" - + "name\":\"tranferTest\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable" - + "\",\"type\":\"function\"}]"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, testKeyForAssetIssue016, asset016Address, blockingStubFull); @@ -524,17 +493,12 @@ public void test6transferTestContract() { @Test(enabled = true, description = "No payable fallback call value") public void test7payableFallbakContract() { - String contractName = "payableFallbak"; - String code = "6080604052348015600f57600080fd5b5060fb8061001e6000396000f3006080604052600436106" - + "03e5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663" - + "32eb12f181146043575b600080fd5b348015604e57600080fd5b50606e73fffffffffffffffffffffffffff" - + "fffffffffffff600435166070565b005b8073ffffffffffffffffffffffffffffffffffffffff1663abcdef" - + "016040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815" - + "26004016000604051808303816000875af150505050505600a165627a7a723058202930f27ada1f076de1a8" - + "57ded5f8b46ef335b465a8edae1b487947d3d7dedcc30029"; - String abi = "[{\"constant\":false,\"inputs\":[{\"name\":\"test\",\"type\":\"address\"}],\"" - + "name\":\"callTest\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable" - + "\",\"type\":\"function\"}]"; + String filePath = + "src/test/resources/soliditycode/requireExceptiontest7payableFallbakContract.sol"; + String contractName = "Caller"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, testKeyForAssetIssue016, asset016Address, blockingStubFull); @@ -542,11 +506,10 @@ public void test7payableFallbakContract() { PublicMethed.waitProduceNextBlock(blockingStubFull1); PublicMethed.waitProduceNextBlock(blockingStubFull); Integer times = 0; - String contractName1 = "TestContract"; - String code1 = "6080604052348015600f57600080fd5b50604380601d6000396000f3006080604052348015600f" - + "57600080fd5b5060016000550000a165627a7a723058205718ecb0cace0afa330fc9447eff8556c5829aeb8" - + "256c62364aaf58efa5bd96c0029"; - String abi1 = "[{\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"fallback\"}]"; + String contractName1 = "Test"; + HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); + String code1 = retMap1.get("byteCode").toString(); + String abi1 = retMap1.get("abI").toString(); byte[] contractAddress1; contractAddress1 = PublicMethed .deployContract(contractName1, abi1, code1, "", maxFeeLimit, 0L, @@ -609,16 +572,12 @@ public void test7payableFallbakContract() { @Test(enabled = true, description = "New contract gas not enough") public void test8newContractGasNoenough() { - String contractName = "ContractGasNoenough"; - String code = "60806040526040516020806100bf83398101604052516000556099806100266000396000f300608" - + "060405260043610603e5763ffffffff7c010000000000000000000000000000000000000000000000000000" - + "000060003504166396964a2281146043575b600080fd5b348015604e57600080fd5b5060556067565b60408" - + "051918252519081900360200190f35b600054815600a165627a7a72305820cb66b6d0ad40d2f5906f6a159f" - + "47bc1a0c7b36676df34078edad0671caabd2370029"; - String abi = "[{\"constant\":true,\"inputs\":[],\"name\":\"accId\",\"outputs\":[{\"name" - + "\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type" - + "\":\"function\"},{\"inputs\":[{\"name\":\"accountId\",\"type\":\"uint256\"}],\"payable" - + "\":true,\"stateMutability\":\"payable\",\"type\":\"constructor\"}]"; + String filePath = + "src/test/resources/soliditycode/requireExceptiontest8newContractGasNoenough.sol"; + String contractName = "Account"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, testKeyForAssetIssue016, asset016Address, blockingStubFull); @@ -626,19 +585,10 @@ public void test8newContractGasNoenough() { PublicMethed.waitProduceNextBlock(blockingStubFull1); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName1 = "ContractGasNoenough"; - String code1 = "608060405234801561001057600080fd5b50610182806100206000396000f30060806040526004" - + "3610603e5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350" - + "41663bf335e6281146043575b600080fd5b348015604e57600080fd5b5060556057565b005b600060016061" - + "6088565b90815260405190819003602001906000f0801580156083573d6000803e3d6000fd5b505050565b6" - + "0405160bf8061009883390190560060806040526040516020806100bf833981016040525160005560998061" - + "00266000396000f300608060405260043610603e5763ffffffff7c010000000000000000000000000000000" - + "000000000000000000000000060003504166396964a2281146043575b600080fd5b348015604e57600080fd" - + "5b5060556067565b60408051918252519081900360200190f35b600054815600a165627a7a72305820cb66b" - + "6d0ad40d2f5906f6a159f47bc1a0c7b36676df34078edad0671caabd2370029a165627a7a72305820b664e1" - + "3ade4d346e9d9b848e75b8ded8d382d2ecacd77561561c3d6b189ad13f0029"; - String abi1 = "[{\"constant\":false,\"inputs\":[],\"name\":\"newAccount\",\"outputs\":[],\"" - + "payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"; + String contractName1 = "Initialize"; + HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); + String code1 = retMap1.get("byteCode").toString(); + String abi1 = retMap1.get("abI").toString(); final byte[] contractAddress1 = PublicMethed .deployContract(contractName1, abi1, code1, "", maxFeeLimit, @@ -699,15 +649,12 @@ public void test8newContractGasNoenough() { @Test(enabled = true, description = "Message used error") public void test9MessageUsedErrorFeed() { - String contractName = "MessageFeed"; - String code = "6080604052348015600f57600080fd5b50609c8061001e6000396000f300608060405260043610" - + "603e5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416" - + "639138fd4c81146043575b600080fd5b348015604e57600080fd5b5060556067565b604080519182525190" - + "81900360200190f35b60006001818082fe00a165627a7a72305820ebb23e69381b99dba3118ec3b715d619" - + "ca395ecfd88820f7e5338579530fb54f0029"; - String abi = "[{\"constant\":false,\"inputs\":[],\"name\":\"divideMathed\",\"outputs\":" - + "[{\"name\":\"ret\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"" - + "nonpayable\",\"type\":\"function\"}]"; + String filePath = + "src/test/resources/soliditycode/requireExceptiontest9MessageUsedErrorFeed.sol"; + String contractName = "MathedFeed"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, testKeyForAssetIssue016, asset016Address, blockingStubFull); @@ -716,19 +663,10 @@ public void test9MessageUsedErrorFeed() { PublicMethed.waitProduceNextBlock(blockingStubFull); final String saleContractString = "\"" + Base58.encode58Check(contractAddress) + "\""; - String contractName1 = "MessageUseContract"; - String code1 = "608060405234801561001057600080fd5b50610149806100206000396000f30060806040526004" - + "36106100405763ffffffff7c010000000000000000000000000000000000000000000000000000000060003" - + "5041663ff04eb898114610045575b600080fd5b34801561005157600080fd5b5061007373ffffffffffffff" - + "ffffffffffffffffffffffffff60043516610085565b60408051918252519081900360200190f35b600081" - + "73ffffffffffffffffffffffffffffffffffffffff16639138fd4c6040518163ffffffff167c0100000000" - + "000000000000000000000000000000000000000000000000028152600401602060405180830381600087803" - + "b1580156100eb57600080fd5b505af11580156100ff573d6000803e3d6000fd5b505050506040513d602081" - + "101561011557600080fd5b5051929150505600a165627a7a72305820733f086bcd980c277618750fe75cdd8" - + "c6faf8f0b01de9521ac9531e8ec3589030029"; - String abi1 = "[{\"constant\":false,\"inputs\":[{\"name\":\"addr\",\"type\":\"address\"}]" - + ",\"name\":\"MathedUse\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable" - + "\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"; + String contractName1 = "MathedUseContract"; + HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); + String code1 = retMap1.get("byteCode").toString(); + String abi1 = retMap1.get("abI").toString(); final byte[] contractAddress1 = PublicMethed .deployContract(contractName1, abi1, code1, "", maxFeeLimit, @@ -788,14 +726,12 @@ public void test9MessageUsedErrorFeed() { @Test(enabled = true, description = "Function used error") public void testFunctionUsedErrorFeed() { - String contractName = "FunctionFeed"; - String code = "6080604052348015600f57600080fd5b50608b8061001e6000396000f3006080604052600436106" - + "03e5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663" - + "19e1aef981146043575b600080fd5b6049605b565b60408051918252519081900360200190f35b34905600a" - + "165627a7a7230582058a5ea8675d6e5710e5b539601c5567f746c197c90a6d6c2fa4626bfd6c107b30029"; - String abi = "[{\"constant\":false,\"inputs\":[],\"name\":\"mValue\",\"outputs\":[{\"name\":" - + "\"ret\",\"type\":\"uint256\"}],\"payable\":true,\"stateMutability\":\"payable\",\"" - + "type\":\"function\"}]"; + String filePath = + "src/test/resources/soliditycode/requireExceptiontestFunctionUsedErrorFeed.sol"; + String contractName = "MessageFeed"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, testKeyForAssetIssue016, asset016Address, blockingStubFull); @@ -805,19 +741,10 @@ public void testFunctionUsedErrorFeed() { final String saleContractString = "\"" + Base58.encode58Check(contractAddress) + "\""; - String contractName1 = "FunctionUseContract"; - String code1 = "608060405234801561001057600080fd5b5061013f806100206000396000f3006080604052600" - + "436106100405763ffffffff7c0100000000000000000000000000000000000000000000000000000000600" - + "0350416637b77267a8114610045575b600080fd5b61006673fffffffffffffffffffffffffffffffffffff" - + "fff60043516610078565b60408051918252519081900360200190f35b60008173fffffffffffffffffffff" - + "fffffffffffffffffff166319e1aef960016040518263ffffffff167c01000000000000000000000000000" - + "00000000000000000000000000000028152600401602060405180830381600088803b1580156100e057600" - + "080fd5b5087f11580156100f4573d6000803e3d6000fd5b50505050506040513d602081101561010b57600" - + "080fd5b5051929150505600a165627a7a723058207dcdb1b3c42bfc00674f226c36b1bbf2ee54a6a6ae6f" - + "2eeace876b0370d83f5b0029"; - String abi1 = "[{\"constant\":false,\"inputs\":[{\"name\":\"addr\",\"type\":\"address\"}]," - + "\"name\":\"messageUse\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable" - + "\":true,\"stateMutability\":\"payable\",\"type\":\"function\"}]"; + String contractName1 = "MessageUseContract"; + HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); + String code1 = retMap1.get("byteCode").toString(); + String abi1 = retMap1.get("abI").toString(); final byte[] contractAddress1 = PublicMethed .deployContract(contractName1, abi1, code1, "", maxFeeLimit, 0L, 100, null, testKeyForAssetIssue016, diff --git a/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount012.java b/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount012.java index 938bd2a08eb..f282f68cfef 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount012.java +++ b/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestAccount012.java @@ -144,7 +144,6 @@ public void storageAndCpu() { 0, maxFeeLimit, asset011Address, testKeyForAssetIssue011, blockingStubFull);*/ PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull1); - PublicMethed.waitProduceNextBlock(blockingStubFull); txid = PublicMethed.triggerContract(contractAddress, "add2(uint256)", initParmes, false, 0, maxFeeLimit, asset011Address, testKeyForAssetIssue011, blockingStubFull); diff --git a/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestWitness003.java b/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestWitness003.java index 586f6169ab5..b4b4714372e 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestWitness003.java +++ b/src/test/java/stest/tron/wallet/dailybuild/manual/WalletTestWitness003.java @@ -58,6 +58,10 @@ public class WalletTestWitness003 { byte[] updateUrl = updateWitnessUrl.getBytes(); byte[] wrongUrl = nullUrl.getBytes(); byte[] updateSpaceUrl = spaceUrl.getBytes(); + private static final String tooLongUrl = "qagwqaswqaswqaswqaswqaswqaswqaswqaswqaswqaswqas" + + "wqaswqasw1qazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazx" + + "swedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedcvqazxswedc" + + "vqazxswedcvqazxswedcvqazxswedcvqazxswedcv"; private ManagedChannel channelFull = null; private WalletGrpc.WalletBlockingStub blockingStubFull = null; private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") @@ -92,7 +96,7 @@ public void beforeClass() { @Test(enabled = true, description = "Invaild account to apply create witness") public void testInvaildToApplyBecomeWitness() { - Assert.assertFalse(createWitness(INVAILD_ADDRESS, createUrl, testKey002)); + Assert.assertFalse(createWitnessNotBroadcast(INVAILD_ADDRESS, createUrl, testKey002)); } @Test(enabled = true, description = "Create witness") @@ -102,7 +106,7 @@ public void testCreateWitness() { //Assert.assertFalse(createWitness(fromAddress, createUrl, testKey002)); //No balance,try to create witness. - Assert.assertFalse(createWitness(lowBalAddress, createUrl, lowBalTest)); + Assert.assertFalse(createWitnessNotBroadcast(lowBalAddress, createUrl, lowBalTest)); //Send enough coin to the apply account to make that account // has ability to apply become witness. @@ -114,6 +118,11 @@ public void testCreateWitness() { Assert.assertTrue(PublicMethed .sendcoin(lowBalAddress, costForCreateWitness, fromAddress, testKey002, blockingStubFull)); + //null url, update failed + Assert.assertFalse(createWitnessNotBroadcast(lowBalAddress, wrongUrl, testUpdateWitnessKey)); + //too long url, update failed + Assert.assertFalse(createWitnessNotBroadcast(lowBalAddress, + tooLongUrl.getBytes(), testUpdateWitnessKey)); Assert.assertTrue(createWitnessNotBroadcast(lowBalAddress, createUrl, lowBalTest)); } @@ -128,6 +137,8 @@ public void testUpdateWitness() { if (result.get().getWitnessesCount() < 6) { //null url, update failed Assert.assertFalse(updateWitness(updateAddress, wrongUrl, testUpdateWitnessKey)); + //too long url, update failed + Assert.assertFalse(updateWitness(updateAddress, tooLongUrl.getBytes(), testUpdateWitnessKey)); //Content space and special char, update success Assert.assertTrue(updateWitness(updateAddress, updateSpaceUrl, testUpdateWitnessKey)); //update success @@ -150,34 +161,6 @@ public void shutdown() throws InterruptedException { } } - /** - * constructor. - */ - - public Boolean createWitness(byte[] owner, byte[] url, String priKey) { - ECKey temKey = null; - try { - BigInteger priK = new BigInteger(priKey, 16); - temKey = ECKey.fromPrivate(priK); - } catch (Exception ex) { - ex.printStackTrace(); - } - final ECKey ecKey = temKey; - - Contract.WitnessCreateContract.Builder builder = Contract.WitnessCreateContract.newBuilder(); - builder.setOwnerAddress(ByteString.copyFrom(owner)); - builder.setUrl(ByteString.copyFrom(url)); - Contract.WitnessCreateContract contract = builder.build(); - Protocol.Transaction transaction = blockingStubFull.createWitness(contract); - if (transaction == null || transaction.getRawData().getContractCount() == 0) { - return false; - } - transaction = signTransaction(ecKey, transaction); - GrpcAPI.Return response = PublicMethed.broadcastTransaction(transaction, blockingStubFull); - return response.getResult(); - - } - /** * constructor. */ diff --git a/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign01.java b/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign01.java index d2dc578d0d7..e649e22b0d9 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign01.java +++ b/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign01.java @@ -752,7 +752,7 @@ public void testOwnerName09() { Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); - + PublicMethed.waitProduceNextBlock(blockingStubFull); Long balanceAfter = PublicMethed.queryAccount(ownerAddress, blockingStubFull) .getBalance(); logger.info("balanceAfter: " + balanceAfter); diff --git a/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign11.java b/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign11.java index 4d18c2da70b..cebd76e5509 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign11.java +++ b/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign11.java @@ -894,6 +894,7 @@ public void testActiveAddress10() { + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey02) + "\",\"weight\":2}," + "{\"address\":\"" + PublicMethed.getAddressString(tmpKey01) + "\",\"weight\":3}" + "]}]}"; + PublicMethed.waitProduceNextBlock(blockingStubFull); Assert.assertTrue(PublicMethedForMutiSign.accountPermissionUpdate(accountPermissionJson, ownerAddress, ownerKey, blockingStubFull, ownerPermissionKeys.toArray(new String[ownerPermissionKeys.size()]))); diff --git a/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign30.java b/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign30.java index cf3347f05e8..e0b8c926e5b 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign30.java +++ b/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign30.java @@ -130,6 +130,7 @@ public void testMultiUpdatepermissions_31() { Transaction transaction = PublicMethedForMutiSign .sendcoinWithPermissionIdNotSign(fromAddress, 1L, test001Address, 2, dev001Key, blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); Transaction transaction1 = PublicMethed .addTransactionSign(transaction, sendAccountKey4, blockingStubFull); diff --git a/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign31.java b/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign31.java index f8c17673455..8877bf29b6b 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign31.java +++ b/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign31.java @@ -334,8 +334,10 @@ public void testMultiUpdatepermissions_36() { TransactionSignWeight transactionSignWeight = PublicMethedForMutiSign .getTransactionSignWeight(transaction1, blockingStubFull); logger.info("transaction:" + transactionSignWeight); + Return returnResult1 = PublicMethedForMutiSign .broadcastTransaction1(transaction1, blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); Assert.assertTrue(returnResult1.getResult()); logger.info("returnResult1:" + returnResult1); @@ -814,6 +816,7 @@ public void testMultiUpdatepermissions_41() { Return returnResult1 = PublicMethedForMutiSign .broadcastTransaction1(transaction1, blockingStubFull); Assert.assertTrue(returnResult1.getResult()); + PublicMethed.waitProduceNextBlock(blockingStubFull); logger.info("returnResult1:" + returnResult1); Account test001AddressAccount2 = PublicMethed.queryAccount(test001Address, blockingStubFull); diff --git a/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign32.java b/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign32.java index 3a4f6297200..8217a7cc024 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign32.java +++ b/src/test/java/stest/tron/wallet/dailybuild/multisign/MultiSign32.java @@ -117,6 +117,7 @@ public void testMultiSignAddDupAssressOwner() { .accountPermissionUpdateWithPermissionId(accountPermissionJson1, test001Address, dev001Key, blockingStubFull, 0, permissionKeyString)); + PublicMethed.waitProduceNextBlock(blockingStubFull); Account test001AddressAccount1 = PublicMethed.queryAccount(test001Address, blockingStubFull); List permissionsList1 = test001AddressAccount1.getActivePermissionList(); diff --git a/src/test/java/stest/tron/wallet/dailybuild/originenergylimit/ContractOriginEnergyLimit001.java b/src/test/java/stest/tron/wallet/dailybuild/originenergylimit/ContractOriginEnergyLimit001.java index de2d06cb959..5097810bfe7 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/originenergylimit/ContractOriginEnergyLimit001.java +++ b/src/test/java/stest/tron/wallet/dailybuild/originenergylimit/ContractOriginEnergyLimit001.java @@ -2,6 +2,7 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; @@ -82,12 +83,11 @@ public void testOrigin_energy_limit001() { blockingStubFull)); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName = "aContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_OriginEnergyLimit001"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_OriginEnergyLimit001"); - + String filePath = "src/test/resources/soliditycode/contractOriginEnergyLimit001.sol"; + String contractName = "findArgsContractTest"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); String contractAddress = PublicMethed .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 0L, 100, -1, "0", 0, diff --git a/src/test/java/stest/tron/wallet/dailybuild/originenergylimit/ContractOriginEnergyLimit004.java b/src/test/java/stest/tron/wallet/dailybuild/originenergylimit/ContractOriginEnergyLimit004.java index b6e48444101..d12e0c4a592 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/originenergylimit/ContractOriginEnergyLimit004.java +++ b/src/test/java/stest/tron/wallet/dailybuild/originenergylimit/ContractOriginEnergyLimit004.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -186,12 +187,11 @@ public void testOriginEnergyLimit() { logger.info("before deploy, dev energy usage is " + Long.toString(devEnergyUsageBefore)); logger.info("before deploy, dev balance is " + Long.toString(devBalanceBefore)); - String contractName = "findArgsByIndex"; - - String code = Configuration.getByPath("testng.conf") - .getString("code.code_OriginEnergyLimit004"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_OriginEnergyLimit004"); + String filePath = "src/test/resources/soliditycode/contractOriginEnergyLimit004.sol"; + String contractName = "findArgsContractTest"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); final String deployTxid = PublicMethed .deployContractAndGetTransactionInfoById(contractName, abi, code, "", diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken001.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken001.java index d43ac5406c8..ecb9d30b4c2 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken001.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken001.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.List; import java.util.Optional; import java.util.concurrent.TimeUnit; @@ -121,11 +122,12 @@ public void deployTransferTokenContract() { logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " + devAssetCountBefore); - String contractName = "transferTokenContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken001_transferTokenContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken001_transferTokenContract"); + String filePath = "./src/test/resources/soliditycode/contractTrcToken001.sol"; + String contractName = "tokenTest"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); String tokenId = assetAccountId.toStringUtf8(); long tokenValue = 100; @@ -153,6 +155,7 @@ public void deployTransferTokenContract() { Optional infoById = PublicMethed .getTransactionInfoById(transferTokenTxid, blockingStubFull); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage() @@ -192,6 +195,8 @@ public void deployTransferTokenContract() { infoById = PublicMethed .getTransactionInfoById(triggerTxid, blockingStubFull); + logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + if (infoById.get().getResultValue() != 0) { Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); } diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken002.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken002.java index 7093f4d230b..1121fade9b8 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken002.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken002.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.List; import java.util.Optional; import java.util.concurrent.TimeUnit; @@ -123,11 +124,12 @@ public void deployTransferTokenContract() { logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " + devAssetCountBefore); - String contractName = "transferTokenContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken002_transferTokenContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken002_transferTokenContract"); + String filePath = "./src/test/resources/soliditycode/contractTrcToken002.sol"; + String contractName = "tokenTest"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); String tokenId = assetAccountId.toStringUtf8(); long tokenValue = 100; @@ -142,6 +144,7 @@ public void deployTransferTokenContract() { Optional infoById = PublicMethed .getTransactionInfoById(transferTokenTxid, blockingStubFull); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); @@ -249,6 +252,8 @@ public void deployTransferTokenContract() { infoById = PublicMethed .getTransactionInfoById(triggerTxid, blockingStubFull); + logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + if (triggerTxid == null || infoById.get().getResultValue() != 0) { Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); } diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken003.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken003.java index 98230210f06..c215d96d973 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken003.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken003.java @@ -5,6 +5,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; @@ -140,18 +141,12 @@ public void deployTransferTokenContract() { PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName = "transferTokenContract"; - String code = "608060405260e2806100126000396000f300608060405260043610603e5763ffffffff7c01000000" - + "000000000000000000000000000000000000000000000000006000350416633be9ece781146043575b600080" - + "fd5b606873ffffffffffffffffffffffffffffffffffffffff60043516602435604435606a565b005b604051" - + "73ffffffffffffffffffffffffffffffffffffffff84169082156108fc029083908590600081818185878a8a" - + "d094505050505015801560b0573d6000803e3d6000fd5b505050505600a165627a7a723058200ba246bdb58b" - + "e0f221ad07e1b19de843ab541150b329ddd01558c2f1cefe1e270029"; - String abi = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}," - + "{\"name\":\"id\",\"type\":\"trcToken\"},{\"name\":\"amount\",\"type\":\"uint256\"}]," - + "\"name\":\"TransferTokenTo\",\"outputs\":[],\"payable\":true,\"stateMutability\":" - + "\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":" - + "\"payable\",\"type\":\"constructor\"}]"; + String filePath = "./src/test/resources/soliditycode/contractTrcToken003.sol"; + String contractName = "tokenTest"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); // the tokenId is not exist String fakeTokenId = Long.toString(Long.valueOf(assetAccountDev.toStringUtf8()) + 100); diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken005.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken005.java index c91bd4e4091..476b91c2dfd 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken005.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken005.java @@ -5,6 +5,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -125,11 +126,13 @@ public void deployTransferTokenContract() { logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " + devAssetCountBefore); - String contractName = "transferTokenContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken005_transferTokenContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken005_transferTokenContract"); + String filePath = "./src/test/resources/soliditycode/contractTrcToken005.sol"; + String contractName = "tokenTest"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + String tokenId = assetAccountId.toStringUtf8(); long tokenValue = 100; long callValue = 0; @@ -143,6 +146,7 @@ public void deployTransferTokenContract() { Optional infoById = PublicMethed .getTransactionInfoById(transferTokenTxid, blockingStubFull); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken011.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken011.java index fdf1af4d635..71390063241 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken011.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken011.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.List; import java.util.Optional; import java.util.concurrent.TimeUnit; @@ -128,11 +129,13 @@ public void test01DeployTransferTokenContract() { logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " + devAssetCountBefore); + String filePath = "./src/test/resources/soliditycode/contractTrcToken011.sol"; String contractName = "transferTokenContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken011_transferTokenContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken011_transferTokenContract"); + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + final String transferTokenTxid = PublicMethed .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 0L, 0, 10000, @@ -156,6 +159,7 @@ public void test01DeployTransferTokenContract() { Optional infoById = PublicMethed .getTransactionInfoById(transferTokenTxid, blockingStubFull); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); if (infoById.get().getResultValue() != 0) { Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); @@ -203,11 +207,12 @@ public void test02DeployRevContract() { logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " + devAssetCountBefore); - String contractName = "resultContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken011_resultContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken011_resultContract"); + String filePath = "./src/test/resources/soliditycode/contractTrcToken011.sol"; + String contractName = "Result"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); final String recieveTokenTxid = PublicMethed .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 0L, 100, 1000, assetAccountId.toStringUtf8(), @@ -230,7 +235,7 @@ public void test02DeployRevContract() { Optional infoById = PublicMethed .getTransactionInfoById(recieveTokenTxid, blockingStubFull); - + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); if (infoById.get().getResultValue() != 0) { Assert.fail("deploy receive failed with message: " + infoById.get().getResMessage()); } @@ -327,7 +332,7 @@ public void test03TriggerContract() { Optional infoById = PublicMethed .getTransactionInfoById(triggerTxid, blockingStubFull); - + logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); TransactionInfo transactionInfo = infoById.get(); logger.info( @@ -430,6 +435,7 @@ public void test04TriggerTokenBalanceContract() { Optional infoById = PublicMethed.getTransactionInfoById(triggerTxid, blockingStubFull); + logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); if (infoById.get().getResultValue() != 0) { Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); } diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken012.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken012.java index be1431c25a7..134e451204b 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken012.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken012.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -119,11 +120,12 @@ public void test01DeployTransferTokenContract() { logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " + devAssetCountBefore); + String filePath = "./src/test/resources/soliditycode/contractTrcToken012.sol"; String contractName = "transferTokenContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken012_transferTokenContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken012_transferTokenContract"); + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); final String transferTokenTxid = PublicMethed .deployContractAndGetTransactionInfoById(contractName, abi, code, "", @@ -147,6 +149,7 @@ public void test01DeployTransferTokenContract() { Optional infoById = PublicMethed .getTransactionInfoById(transferTokenTxid, blockingStubFull); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); @@ -246,6 +249,8 @@ public void test02TriggerContract() { Optional infoById = PublicMethed .getTransactionInfoById(triggerTxid, blockingStubFull); + logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + if (triggerTxid == null || infoById.get().getResultValue() != 0) { Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); } @@ -327,6 +332,8 @@ public void test03TriggerTokenBalanceContract() { Optional infoById = PublicMethed.getTransactionInfoById(triggerTxid, blockingStubFull); + logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + if (triggerTxid == null || infoById.get().getResultValue() != 0) { Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); } diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken014.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken014.java index c2103939a27..d2909dc6b07 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken014.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken014.java @@ -5,6 +5,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -139,11 +140,13 @@ public void test01DeployTransferTokenContract() { logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " + devAssetCountBefore); + String filePath = "./src/test/resources/soliditycode/contractTrcToken014.sol"; String contractName = "transferTokenContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken014_transferTokenContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken014_transferTokenContract"); + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + String transferTokenTxid = PublicMethed .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 0L, 0, 10000, @@ -153,6 +156,7 @@ public void test01DeployTransferTokenContract() { Optional infoById = PublicMethed .getTransactionInfoById(transferTokenTxid, blockingStubFull); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); @@ -211,11 +215,13 @@ public void test02DeployRevContract() { logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " + devAssetCountBefore); - String contractName = "resultContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken014_resultContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken014_resultContract"); + String filePath = "./src/test/resources/soliditycode/contractTrcToken014.sol"; + String contractName = "Result"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + String recieveTokenTxid = PublicMethed .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 0L, 100, 1000, assetAccountId.toStringUtf8(), @@ -324,6 +330,7 @@ public void test03TriggerContract() { Optional infoById = PublicMethed .getTransactionInfoById(triggerTxid, blockingStubFull); + Assert.assertTrue(infoById.get().getResultValue() != 0); Assert.assertEquals(FAILED, infoById.get().getResult()); Assert.assertEquals("REVERT opcode executed", @@ -373,9 +380,10 @@ public void test03TriggerContract() { "transferTokenTest(address,uint256,trcToken)", param, false, callValue, 1000000000L, assetAccountId.toStringUtf8(), 2, user001Address, user001Key, blockingStubFull); - + PublicMethed.waitProduceNextBlock(blockingStubFull); infoById = PublicMethed .getTransactionInfoById(triggerTxid, blockingStubFull); + Assert.assertTrue(infoById.get().getResultValue() != 0); Assert.assertEquals(FAILED, infoById.get().getResult()); Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); @@ -524,7 +532,7 @@ public void test03TriggerContract() { .getTransactionInfoById(triggerTxid, blockingStubFull); Assert.assertTrue(infoById.get().getResultValue() != 0); Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("BigInteger out of long range", + Assert.assertEquals("endowment out of long range", infoById.get().getResMessage().toStringUtf8()); Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, @@ -546,7 +554,7 @@ public void test03TriggerContract() { .getTransactionInfoById(triggerTxid, blockingStubFull); Assert.assertTrue(infoById.get().getResultValue() != 0); Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("BigInteger out of long range", + Assert.assertEquals("endowment out of long range", infoById.get().getResMessage().toStringUtf8()); accountResource = PublicMethed.getAccountResource(dev001Address, blockingStubFull); diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken018.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken018.java index 4c85b784821..813dab94b76 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken018.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken018.java @@ -5,6 +5,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -128,18 +129,12 @@ public void testDeployTransferTokenContract() { logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " + devAssetCountBefore); - String contractName = "transferTokenContract"; - String code = "608060405260e2806100126000396000f300608060405260043610603e5763ffffffff7c01000000" - + "000000000000000000000000000000000000000000000000006000350416633be9ece781146043575b600080" - + "fd5b606873ffffffffffffffffffffffffffffffffffffffff60043516602435604435606a565b005b604051" - + "73ffffffffffffffffffffffffffffffffffffffff84169082156108fc029083908590600081818185878a8a" - + "d094505050505015801560b0573d6000803e3d6000fd5b505050505600a165627a7a723058200ba246bdb58b" - + "e0f221ad07e1b19de843ab541150b329ddd01558c2f1cefe1e270029"; - String abi = "[{\"constant\":false,\"inputs\":[{\"name\":\"toAddress\",\"type\":\"address\"}," - + "{\"name\":\"id\",\"type\":\"trcToken\"},{\"name\":\"amount\",\"type\":\"uint256\"}]," - + "\"name\":\"TransferTokenTo\",\"outputs\":[],\"payable\":true,\"stateMutability\":" - + "\"payable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":true,\"stateMutability\":" - + "\"payable\",\"type\":\"constructor\"}]"; + String filePath = "./src/test/resources/soliditycode/contractTrcToken023.sol"; + String contractName = "tokenTest"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); String transferTokenTxid = PublicMethed .deployContractAndGetTransactionInfoById(contractName, abi, code, "", @@ -150,6 +145,7 @@ public void testDeployTransferTokenContract() { Optional infoById = PublicMethed .getTransactionInfoById(transferTokenTxid, blockingStubFull); + logger.info("Delpoy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); @@ -261,9 +257,12 @@ public void testDeployTransferTokenContract() { infoById = PublicMethed .getTransactionInfoById(triggerTxid, blockingStubFull); + logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("validateForSmartContract failure", + Assert.assertEquals( + "transfer trc10 failed: Validate InternalTransfer error, no ToAccount. " + + "And not allowed to create account in smart contract.", infoById.get().getResMessage().toStringUtf8()); Long transferAssetAfter = PublicMethed.getAssetIssueValue(transferTokenContractAddress, diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken023.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken023.java index 00916427321..3956a0d472e 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken023.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken023.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -123,23 +124,21 @@ public void deploy01TransferTokenContract() { // deploy transferTokenContract int originEnergyLimit = 50000; + String filePath2 = "src/test/resources/soliditycode/contractTrcToken023.sol"; String contractName2 = "tokenTest"; - String code2 = Configuration.getByPath("testng.conf") - .getString("code.code2_ContractTrcToken023_tokenTest"); - String abi2 = Configuration.getByPath("testng.conf") - .getString("abi.abi2_ContractTrcToken023_tokenTest"); + HashMap retMap2 = PublicMethed.getBycodeAbi(filePath2, contractName2); + String code2 = retMap2.get("byteCode").toString(); + String abi2 = retMap2.get("abI").toString(); transferTokenContractAddress = PublicMethed .deployContract(contractName2, abi2, code2, "", maxFeeLimit, 0L, 0, originEnergyLimit, "0", 0, null, dev001Key, dev001Address, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - - String contractName = "BTest"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken023_tokenTest"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken023_tokenTest"); + String contractName = "B"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath2, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); btestAddress = PublicMethed .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 0, originEnergyLimit, "0", diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken026.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken026.java index fd9fb307322..fd9ac39abff 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken026.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken026.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -120,11 +121,11 @@ public void deploy01TransferTokenContract() { // deploy transferTokenContract int originEnergyLimit = 50000; - String contractName = "BTest"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken026_BTest"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken026_BTest"); + String filePath = "src/test/resources/soliditycode/contractTrcToken026.sol"; + String contractName = "B"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); btestAddress = PublicMethed .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 0, originEnergyLimit, "0", @@ -133,11 +134,10 @@ public void deploy01TransferTokenContract() { PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String code1 = Configuration.getByPath("testng.conf") - .getString("code.code1_ContractTrcToken026_CTest"); - String abi1 = Configuration.getByPath("testng.conf") - .getString("abi.abi1_ContractTrcToken026_CTest"); - String contractName1 = "CTest"; + String contractName1 = "C"; + HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); + String code1 = retMap1.get("byteCode").toString(); + String abi1 = retMap1.get("abI").toString(); ctestAddress = PublicMethed .deployContract(contractName1, abi1, code1, "", maxFeeLimit, 0L, 0, originEnergyLimit, "0", @@ -145,11 +145,10 @@ public void deploy01TransferTokenContract() { blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName2 = "tokenTest"; - String code2 = Configuration.getByPath("testng.conf") - .getString("code.code1_ContractTrcToken026_tokenTest"); - String abi2 = Configuration.getByPath("testng.conf") - .getString("abi.abi1_ContractTrcToken026_tokenTest"); + String contractName2 = "token"; + HashMap retMap2 = PublicMethed.getBycodeAbi(filePath, contractName2); + String code2 = retMap2.get("byteCode").toString(); + String abi2 = retMap2.get("abI").toString(); transferTokenContractAddress = PublicMethed .deployContract(contractName2, abi2, code2, "", maxFeeLimit, 0L, 0, originEnergyLimit, "0", diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken027.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken027.java index 8ecb1f17d61..086ac2f39d4 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken027.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken027.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -125,11 +126,11 @@ public void deploy01TransferTokenContract() { // deploy transferTokenContract int originEnergyLimit = 50000; - String contractName = "BTest"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken027_BTest"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken027_BTest"); + String filePath = "src/test/resources/soliditycode/contractTrcToken027.sol"; + String contractName = "B"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); btestAddress = PublicMethed .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 0, originEnergyLimit, "0", @@ -138,11 +139,10 @@ public void deploy01TransferTokenContract() { PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName1 = "CTest"; - String code1 = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken027_CTest"); - String abi1 = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken027_CTest"); + String contractName1 = "C"; + HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); + String code1 = retMap1.get("byteCode").toString(); + String abi1 = retMap1.get("abI").toString(); ctestAddress = PublicMethed .deployContract(contractName1, abi1, code1, "", maxFeeLimit, 0L, 0, originEnergyLimit, "0", @@ -151,11 +151,11 @@ public void deploy01TransferTokenContract() { PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName2 = "tokenTest"; - String code2 = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken027_tokenTest"); - String abi2 = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken027_tokenTest"); + String contractName2 = "token"; + HashMap retMap2 = PublicMethed.getBycodeAbi(filePath, contractName2); + + String code2 = retMap2.get("byteCode").toString(); + String abi2 = retMap2.get("abI").toString(); transferTokenContractAddress = PublicMethed .deployContract(contractName2, abi2, code2, "", maxFeeLimit, 0L, 0, originEnergyLimit, "0", diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken028.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken028.java index 21075470e18..dd60b41e31a 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken028.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken028.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -120,11 +121,11 @@ public void deploy01TransferTokenContract() { assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); // deploy transferTokenContract int originEnergyLimit = 50000; - String contractName = "tokenTest"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken028_tokenTest"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken028_tokenTest"); + String filePath = "src/test/resources/soliditycode/contractTrcToken028.sol"; + String contractName = "token"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); transferTokenContractAddress = PublicMethed .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 0, originEnergyLimit, "0", diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken029.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken029.java index 5e88b8a79d5..54793e73c38 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken029.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken029.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -111,11 +112,11 @@ public void deploy01TransferTokenContract() { // deploy transferTokenContract int originEnergyLimit = 50000; - String contractName = "tokenTest"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken029_tokenTest"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken029_tokenTest"); + String filePath = "src/test/resources/soliditycode/contractTrcToken029.sol"; + String contractName = "token"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); transferTokenContractAddress = PublicMethed .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 0, originEnergyLimit, "0", @@ -230,9 +231,9 @@ public void deploy02TransferTokenContract() { Assert.assertEquals(afterUserBalance, beforeUserBalance); Assert.assertTrue(afterAssetIssueContractAddress == beforeAssetIssueContractAddress); PublicMethed.unFreezeBalance(dev001Address, dev001Key, 1, - dev001Address, blockingStubFull); + null, blockingStubFull); PublicMethed.unFreezeBalance(user001Address, user001Key, 1, - user001Address, blockingStubFull); + null, blockingStubFull); } /** diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken030.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken030.java index af179c76ac6..6871dbc3769 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken030.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken030.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -110,11 +111,11 @@ public void deploy01TransferTokenContract() { // deploy transferTokenContract int originEnergyLimit = 50000; - String contractName = "tokenTest"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken030_tokenTest"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken030_tokenTest"); + String filePath = "src/test/resources/soliditycode/contractTrcToken030.sol"; + String contractName = "token"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); transferTokenContractAddress = PublicMethed .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 0, originEnergyLimit, "0", diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken031.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken031.java index c892d0194ba..6b7e4877180 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken031.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken031.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -111,17 +112,19 @@ public void deploy01TransferTokenContract() { // deploy transferTokenContract int originEnergyLimit = 50000; - String contractName = "tokenTest"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken031_tokenTest"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken031_tokenTest"); + String filePath = "src/test/resources/soliditycode/contractTrcToken031.sol"; + String contractName = "token"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); transferTokenContractAddress = PublicMethed .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 0, originEnergyLimit, "0", 0, null, dev001Key, dev001Address, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); + Assert.assertNotNull(transferTokenContractAddress); + Assert .assertTrue(PublicMethed.sendcoin(transferTokenContractAddress, 1000000000L, fromAddress, testKey002, blockingStubFull)); diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken034.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken034.java index 14cb75bdc54..943ca4a9144 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken034.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken034.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -112,11 +113,11 @@ public void deploy01TransferTokenContract() { // deploy transferTokenContract int originEnergyLimit = 50000; - String contractName = "tokenTest"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken034_tokenTest"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken034_tokenTest"); + String filePath = "src/test/resources/soliditycode/contractTrcToken034.sol"; + String contractName = "token"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); transferTokenContractAddress = PublicMethed .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 0, originEnergyLimit, "0", diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken035.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken035.java index 8025d9e0453..f4861b96364 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken035.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken035.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -114,11 +115,11 @@ public void deploy01TransferTokenContract() { // deploy transferTokenContract int originEnergyLimit = 50000; - String contractName = "tokenTest"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken035_tokenTest"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken035_tokenTest"); + String filePath = "src/test/resources/soliditycode/contractTrcToken035.sol"; + String contractName = "token"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); transferTokenContractAddress = PublicMethed .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 0, originEnergyLimit, "0", diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken036.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken036.java index 1cc1fe53135..21895f3edae 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken036.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken036.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -78,7 +79,7 @@ public void beforeClass() { } - @Test(enabled = true, description = "Deploy contract") + @Test(enabled = false, description = "Deploy contract") public void deploy01TransferTokenContract() { Assert @@ -114,32 +115,32 @@ public void deploy01TransferTokenContract() { assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); // deploy transferTokenContract - String contractName = "tokenTest"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken036_tokenTest"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken036_tokenTest"); - transferTokenContractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 0, originEnergyLimit, "0", - 0, null, dev001Key, dev001Address, - blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); - - // devAddress transfer token to userAddress - PublicMethed - .transferAsset(transferTokenContractAddress, assetAccountId.toByteArray(), 100, - dev001Address, - dev001Key, - blockingStubFull); - Assert - .assertTrue(PublicMethed.sendcoin(transferTokenContractAddress, 100, fromAddress, - testKey002, blockingStubFull)); + // String filePath = "src/test/resources/soliditycode/contractTrcToken036.sol"; + // String contractName = "IllegalDecorate"; + // HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + // String code = retMap.get("byteCode").toString(); + // String abi = retMap.get("abI").toString(); + // transferTokenContractAddress = PublicMethed + // .deployContract(contractName, abi, code, "", maxFeeLimit, + // 0L, 0, originEnergyLimit, "0", + // 0, null, dev001Key, dev001Address, + // blockingStubFull); + // PublicMethed.waitProduceNextBlock(blockingStubFull); + // PublicMethed.waitProduceNextBlock(blockingStubFull); + // + // // devAddress transfer token to userAddress + // PublicMethed + // .transferAsset(transferTokenContractAddress, assetAccountId.toByteArray(), 100, + // dev001Address, + // dev001Key, + // blockingStubFull); + // Assert + // .assertTrue(PublicMethed.sendcoin(transferTokenContractAddress, 100, fromAddress, + // testKey002, blockingStubFull)); PublicMethed.waitProduceNextBlock(blockingStubFull); } - @Test(enabled = true, description = "Trigger transferTokenWithPure contract") + @Test(enabled = false, description = "Trigger transferTokenWithPure contract") public void deploy02TransferTokenContract() { Account info; AccountResourceMessage resourceInfo = PublicMethed.getAccountResource(dev001Address, @@ -220,11 +221,11 @@ public void deploy02TransferTokenContract() { Assert.assertTrue(beforeAssetIssueUserAddress + 10 == afterAssetIssueUserAddress); Assert.assertTrue(user001AddressAddressBalance + 10 == afteruser001AddressAddressBalance); - String contractName1 = "transferTokenWithPureTest"; - String code1 = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken036_transferTokenWithPureTest"); - String abi1 = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken036_transferTokenWithPureTest"); + String filePath = "src/test/resources/soliditycode/contractTrcToken036.sol"; + String contractName1 = "IllegalDecorate1"; + HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); + String code1 = retMap1.get("byteCode").toString(); + String abi1 = retMap1.get("abI").toString(); transferTokenWithPureTestAddress = PublicMethed .deployContract(contractName1, abi1, code1, "", maxFeeLimit, 0L, 0, originEnergyLimit, "0", @@ -245,7 +246,7 @@ public void deploy02TransferTokenContract() { PublicMethed.waitProduceNextBlock(blockingStubFull); } - @Test(enabled = true, description = "Trigger transferTokenWithConstant contract") + @Test(enabled = false, description = "Trigger transferTokenWithConstant contract") public void deploy03TransferTokenContract() { Account info1; AccountResourceMessage resourceInfo1 = PublicMethed.getAccountResource(dev001Address, @@ -327,14 +328,14 @@ public void deploy03TransferTokenContract() { Assert.assertEquals(user001AddressAddressBalance1, afteruser001AddressAddressBalance1); } - @Test(enabled = true, description = "Trigger transferTokenWithView contract") + @Test(enabled = false, description = "Trigger transferTokenWithView contract") public void deploy04TransferTokenContract() { - String contractName2 = "transferTokenWithViewTest"; + String filePath2 = "src/test/resources/soliditycode/contractTrcToken036.sol"; + String contractName2 = "IllegalDecorate2"; + HashMap retMap2 = PublicMethed.getBycodeAbi(filePath2, contractName2); - String code2 = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken036_transferTokenWithViewTest"); - String abi2 = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken036_transferTokenWithViewTest"); + String code2 = retMap2.get("byteCode").toString(); + String abi2 = retMap2.get("abI").toString(); byte[] transferTokenWithViewAddress = PublicMethed .deployContract(contractName2, abi2, code2, "", maxFeeLimit, 0L, 0, originEnergyLimit, "0", @@ -423,13 +424,14 @@ public void deploy04TransferTokenContract() { Assert.assertEquals(user001AddressAddressBalance2, afteruser001AddressAddressBalance2); } - @Test(enabled = true, description = "Trigger transferTokenWithNoPayable contract") + @Test(enabled = false, description = "Trigger transferTokenWithNoPayable contract") public void deploy05TransferTokenContract() { - String contractName3 = "transferTokenWithOutPayableTest"; - String code3 = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken036_transferTokenWithOutPayableTest"); - String abi3 = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken036_transferTokenWithOutPayableTest"); + String filePath = "src/test/resources/soliditycode/contractTrcToken036.sol"; + String contractName3 = "IllegalDecorate3"; + HashMap retMap3 = PublicMethed.getBycodeAbi(filePath, contractName3); + + String code3 = retMap3.get("byteCode").toString(); + String abi3 = retMap3.get("abI").toString(); byte[] transferTokenWithOutPayableTestAddress = PublicMethed .deployContract(contractName3, abi3, code3, "", maxFeeLimit, 0L, 0, originEnergyLimit, "0", @@ -517,9 +519,9 @@ public void deploy05TransferTokenContract() { Assert.assertEquals(beforeAssetIssueUserAddress3, afterAssetIssueUserAddress3); Assert.assertEquals(user001AddressAddressBalance3, afteruser001AddressAddressBalance3); PublicMethed.unFreezeBalance(dev001Address, dev001Key, 1, - dev001Address, blockingStubFull); + null, blockingStubFull); PublicMethed.unFreezeBalance(user001Address, user001Key, 1, - user001Address, blockingStubFull); + null, blockingStubFull); } diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken037.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken037.java index e3136fd585d..0d5a7c636ea 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken037.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken037.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -115,22 +116,21 @@ public void deploy01TransferTokenContract() { // deploy transferTokenContract int originEnergyLimit = 50000; - String contractName = "receiveTrc10Test"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken037_receiveTrc10Test"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken037_receiveTrc10Test"); + String filePath = "src/test/resources/soliditycode/contractTrcToken037.sol"; + String contractName = "receiveTrc10"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); byte[] btestAddress = PublicMethed .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 0, originEnergyLimit, "0", 0, null, dev001Key, dev001Address, blockingStubFull); - String contractName1 = "tokenTest"; - String code1 = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken037_tokenTest"); - String abi1 = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken037_tokenTest"); + String contractName1 = "transferTrc10"; + HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); + String code1 = retMap1.get("byteCode").toString(); + String abi1 = retMap1.get("abI").toString(); byte[] transferTokenContractAddress = PublicMethed .deployContract(contractName1, abi1, code1, "", maxFeeLimit, 0L, 0, originEnergyLimit, "0", diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken038.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken038.java index b4559cd2b66..3cac1f8d606 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken038.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken038.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -110,15 +111,17 @@ public void deployTransferTokenContract() { 10000L, 1L, 1L, dev001Key, blockingStubFull)); assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); PublicMethed.waitProduceNextBlock(blockingStubFull); + Assert.assertFalse(assetAccountId.toStringUtf8().equals("")); + // deploy transferTokenContract int originEnergyLimit = 50000; - String contractName2 = "tokenTest"; - String code2 = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken038_tokenTest"); - String abi2 = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken038_tokenTest"); + String filePath = "src/test/resources/soliditycode/contractTrcToken038.sol"; + String contractName2 = "transferTrc10"; + HashMap retMap2 = PublicMethed.getBycodeAbi(filePath, contractName2); + String code2 = retMap2.get("byteCode").toString(); + String abi2 = retMap2.get("abI").toString(); final byte[] transferTokenContractAddress = PublicMethed .deployContract(contractName2, abi2, code2, "", maxFeeLimit, 0L, 0, originEnergyLimit, "0", @@ -127,11 +130,10 @@ public void deployTransferTokenContract() { PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName = "BTest"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken038_BTest"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken038_BTest"); + String contractName = "receiveTrc10"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); byte[] btestAddress = PublicMethed .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 0, originEnergyLimit, "0", @@ -244,9 +246,9 @@ public void deployTransferTokenContract() { Assert.assertTrue(afterAssetIssueContractAddress == beforeAssetIssueContractAddress); Assert.assertTrue(afterAssetIssueBAddress == beforeAssetIssueBAddress); PublicMethed.unFreezeBalance(dev001Address, dev001Key, 1, - dev001Address, blockingStubFull); + null, blockingStubFull); PublicMethed.unFreezeBalance(user001Address, user001Key, 1, - user001Address, blockingStubFull); + null, blockingStubFull); } /** diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken039.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken039.java index 40b16a82eb0..0470715bc36 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken039.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken039.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -115,11 +116,11 @@ public void deploy01TransferTokenContract() { // deploy transferTokenContract int originEnergyLimit = 50000; - String contractName = "ProxyTest"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken039_ProxyTest"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken039_ProxyTest"); + String filePath = "src/test/resources/soliditycode/contractTrcToken039.sol"; + String contractName = "Proxy"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); proxyTestAddress = PublicMethed .deployContract(contractName, abi, code, "", maxFeeLimit, 1000L, 0, originEnergyLimit, assetAccountId.toStringUtf8(), @@ -128,11 +129,10 @@ public void deploy01TransferTokenContract() { PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName1 = "ATest"; - String code1 = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken039_ATest"); - String abi1 = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken039_ATest"); + String contractName1 = "A"; + HashMap retMap1 = PublicMethed.getBycodeAbi(filePath, contractName1); + String code1 = retMap1.get("byteCode").toString(); + String abi1 = retMap1.get("abI").toString(); atestAddress = PublicMethed .deployContract(contractName1, abi1, code1, "", maxFeeLimit, 0L, 0, originEnergyLimit, "0", @@ -141,11 +141,10 @@ public void deploy01TransferTokenContract() { PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName2 = "BTest"; - String code2 = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken039_BTest"); - String abi2 = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken039_BTest"); + String contractName2 = "B"; + HashMap retMap2 = PublicMethed.getBycodeAbi(filePath, contractName2); + String code2 = retMap2.get("byteCode").toString(); + String abi2 = retMap2.get("abI").toString(); btestAddress = PublicMethed .deployContract(contractName2, abi2, code2, "", maxFeeLimit, 0L, 0, originEnergyLimit, "0", diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken041.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken041.java index acc4e0af14f..5fcaad6f0f7 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken041.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken041.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -125,11 +126,11 @@ public void deployTransferTokenContract() { PublicMethed.waitProduceNextBlock(blockingStubFull); // deploy transferTokenContract - String contractName = "transferTokenContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken041_transferTokenContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken041_transferTokenContract"); + String filePath = "src/test/resources/soliditycode/contractTrcToken041.sol"; + String contractName = "tokenTest"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); byte[] transferTokenContractAddress = PublicMethed .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, 10000, assetAccountId.toStringUtf8(), diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken043.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken043.java index d439744a36f..ba1aa82dcd0 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken043.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken043.java @@ -5,6 +5,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -137,11 +138,12 @@ public void test01DeployTransferTokenContract() { logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " + devAssetCountBefore); + String filePath = "./src/test/resources/soliditycode/contractTrcToken043.sol"; String contractName = "transferTokenContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken071_transferTokenContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken071_transferTokenContract"); + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); String transferTokenTxid = PublicMethed .deployContractAndGetTransactionInfoById(contractName, abi, code, "", @@ -153,6 +155,7 @@ public void test01DeployTransferTokenContract() { Optional infoById = PublicMethed .getTransactionInfoById(transferTokenTxid, blockingStubFull); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); @@ -208,11 +211,13 @@ public void test02DeployRevContract() { logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " + devAssetCountBefore); - String contractName = "resultContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken043_recieveTokenContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken043_recieveTokenContract"); + String filePath = "./src/test/resources/soliditycode/contractTrcToken043.sol"; + String contractName = "Result"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + final String recieveTokenTxid = PublicMethed .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 0L, 100, 1000, assetAccountId.toStringUtf8(), @@ -235,6 +240,7 @@ public void test02DeployRevContract() { Optional infoById = PublicMethed .getTransactionInfoById(recieveTokenTxid, blockingStubFull); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); if (recieveTokenTxid == null || infoById.get().getResultValue() != 0) { Assert.fail("deploy receive failed with message: " + infoById.get().getResMessage()); @@ -317,9 +323,11 @@ public void test03TriggerContract() { Optional infoById = PublicMethed .getTransactionInfoById(triggerTxid, blockingStubFull); + logger.info("Triger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + Assert.assertTrue(infoById.get().getResultValue() != 0); Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("validateForSmartContract failure, not valid token id", + Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, @@ -352,7 +360,8 @@ public void test03TriggerContract() { .getTransactionInfoById(triggerTxid, blockingStubFull); Assert.assertTrue(infoById.get().getResultValue() != 0); Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("validateForSmartContract failure, not valid token id", + //Assert.assertEquals("validateForSmartContract failure, not valid token id", + Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, @@ -379,7 +388,7 @@ public void test03TriggerContract() { .getTransactionInfoById(triggerTxid, blockingStubFull); Assert.assertTrue(infoById.get().getResultValue() != 0); Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("validateForSmartContract failure, not valid token id", + Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, @@ -407,7 +416,7 @@ public void test03TriggerContract() { .getTransactionInfoById(triggerTxid, blockingStubFull); Assert.assertTrue(infoById.get().getResultValue() != 0); Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("validateForSmartContract failure, not valid token id", + Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, @@ -434,7 +443,7 @@ public void test03TriggerContract() { .getTransactionInfoById(triggerTxid, blockingStubFull); Assert.assertTrue(infoById.get().getResultValue() != 0); Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("validateForSmartContract failure, not valid token id", + Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, @@ -456,7 +465,7 @@ public void test03TriggerContract() { .getTransactionInfoById(triggerTxid, blockingStubFull); Assert.assertTrue(infoById.get().getResultValue() != 0); Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("validateForSmartContract failure, not valid token id", + Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, @@ -492,7 +501,7 @@ public void test03TriggerContract() { .getTransactionInfoById(triggerTxid, blockingStubFull); Assert.assertTrue(infoById.get().getResultValue() != 0); Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("validateForSmartContract failure, not valid token id", + Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, @@ -519,7 +528,7 @@ public void test03TriggerContract() { .getTransactionInfoById(triggerTxid, blockingStubFull); Assert.assertTrue(infoById.get().getResultValue() != 0); Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("validateForSmartContract failure, not valid token id", + Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, @@ -543,7 +552,7 @@ public void test03TriggerContract() { .getTransactionInfoById(triggerTxid, blockingStubFull); Assert.assertTrue(infoById.get().getResultValue() != 0); Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("BigInteger out of long range", + Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); Assert.assertTrue(PublicMethed.freezeBalanceForReceiver(fromAddress, @@ -564,7 +573,7 @@ public void test03TriggerContract() { infoById = PublicMethed.getTransactionInfoById(triggerTxid, blockingStubFull); Assert.assertTrue(infoById.get().getResultValue() != 0); Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("BigInteger out of long range", + Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); Long transferAssetAfter = PublicMethed.getAssetIssueValue(transferTokenContractAddress, diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken048.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken048.java index 847b6fc9e8b..7b58d3350bc 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken048.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken048.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -116,11 +117,13 @@ public void deployTransferTokenContract() { user001Key, blockingStubFull); // deploy transferTokenContract - String contractName = "transferTokenContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken048_transferTokenContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken048_transferTokenContract"); + String filePath = "./src/test/resources/soliditycode/contractTrcToken048.sol"; + String contractName = "Test"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + byte[] transferTokenContractAddress = PublicMethed .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, 10000, "0", @@ -199,6 +202,8 @@ public void deployTransferTokenContract() { Optional infoById = PublicMethed .getTransactionInfoById(triggerTxid, blockingStubFull); + logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + Assert.assertEquals(beforeBalance, afterBalance); Assert.assertEquals(beforeAssetIssueCount, afterAssetIssueCount); Assert.assertEquals(beforeAssetIssueContractAddress, afterAssetIssueContractAddress); diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken049.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken049.java index adbe4a27b6f..1e6a11be5ed 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken049.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken049.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -146,18 +147,24 @@ public void deployTransferTokenContract() { PublicMethed.waitProduceNextBlock(blockingStubFull); // deploy transferTokenContract - String contractName = "transferTokenContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken049_transferTokenContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken049_transferTokenContract"); - byte[] transferTokenContractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, + String filePath = "./src/test/resources/soliditycode/contractTrcToken049.sol"; + String contractName = "tokenTest"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + + String txid = PublicMethed + .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 0L, 100, 10000, tokenId.toStringUtf8(), 0, null, dev001Key, dev001Address, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); + Optional infoById = PublicMethed + .getTransactionInfoById(txid, blockingStubFull); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + byte[] transferTokenContractAddress = infoById.get().getContractAddress().toByteArray(); // devAddress transfer token to userAddress PublicMethed @@ -222,8 +229,10 @@ public void deployTransferTokenContract() { logger.info("afterAssetIssueCount:" + afterAssetIssueCount); logger.info("afterAssetIssueContractAddress:" + afterAssetIssueContractAddress); - Optional infoById = PublicMethed + infoById = PublicMethed .getTransactionInfoById(triggerTxid, blockingStubFull); + logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + Assert.assertTrue(infoById.get().getResultValue() == 0); Assert.assertEquals(beforeBalance, afterBalance); Assert.assertEquals(beforeAssetIssueCount, afterAssetIssueCount); diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken050.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken050.java index ea3b7695264..b60c75bd32d 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken050.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken050.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -110,22 +111,30 @@ public void deployTransferTokenContract() { assetAccountId = PublicMethed.queryAccount(dev001Address, blockingStubFull).getAssetIssuedID(); // devAddress transfer token to A - PublicMethed.transferAsset(dev001Address, assetAccountId.toByteArray(), 101, user001Address, - user001Key, blockingStubFull); + PublicMethed.transferAsset(user001Address, assetAccountId.toByteArray(), 101, dev001Address, + dev001Key, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); // deploy transferTokenContract - String contractName = "transferTokenContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken050_transferTokenContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken050_transferTokenContract"); - byte[] transferTokenContractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, + + String filePath = "./src/test/resources/soliditycode/contractTrcToken050.sol"; + String contractName = "tokenTest"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + + byte[] transferTokenContractAddress; + String txid = PublicMethed + .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 0L, 100, 10000, assetAccountId.toStringUtf8(), 0, null, dev001Key, dev001Address, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); + Optional infoById = PublicMethed + .getTransactionInfoById(txid, blockingStubFull); + transferTokenContractAddress = infoById.get().getContractAddress().toByteArray(); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); // devAddress transfer token to userAddress PublicMethed @@ -200,8 +209,9 @@ public void deployTransferTokenContract() { logger.info("afterAssetIssueContractAddress:" + afterAssetIssueContractAddress); logger.info("afterAssetIssueDev:" + afterAssetIssueDev); - Optional infoById = PublicMethed - .getTransactionInfoById(triggerTxid, blockingStubFull); + infoById = PublicMethed.getTransactionInfoById(triggerTxid, blockingStubFull); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + Assert.assertTrue(infoById.get().getResultValue() == 1); Assert.assertEquals(beforeAssetIssueCount, afterAssetIssueCount); Assert.assertTrue(beforeAssetIssueContractAddress == afterAssetIssueContractAddress); diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken051.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken051.java index cf3e581935b..2c892c19608 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken051.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken051.java @@ -5,6 +5,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -116,17 +117,25 @@ public void deployTransferTokenContract() { PublicMethed.waitProduceNextBlock(blockingStubFull); // deploy transferTokenContract - String contractName = "transferTokenContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken051_transferTokenContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken051_transferTokenContract"); - byte[] transferTokenContractAddress = PublicMethed - .deployContract(contractName, abi, code, "", maxFeeLimit, + String filePath = "./src/test/resources/soliditycode/contractTrcToken051.sol"; + String contractName = "tokenTest"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + byte[] transferTokenContractAddress; + String txid = PublicMethed + .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 0L, 100, 10000, assetAccountId.toStringUtf8(), 0, null, dev001Key, dev001Address, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); + Optional infoById = PublicMethed + .getTransactionInfoById(txid, blockingStubFull); + Assert.assertTrue(infoById.get().getResultValue() == 0); + transferTokenContractAddress = infoById.get().getContractAddress().toByteArray(); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + Assert .assertTrue(PublicMethed.sendcoin(transferTokenContractAddress, 2048000000, fromAddress, testKey002, blockingStubFull)); @@ -209,11 +218,11 @@ public void deployTransferTokenContract() { logger.info("afterAssetIssueContractAddress:" + afterAssetIssueContractAddress); logger.info("afterAssetIssueDev:" + afterAssetIssueDev); - Optional infoById = PublicMethed + infoById = PublicMethed .getTransactionInfoById(triggerTxid, blockingStubFull); Assert.assertFalse(infoById.get().getResultValue() == 0); Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("validateForSmartContract failure, not valid token id", + Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); Assert.assertEquals(beforeAssetIssueCount, afterAssetIssueCount); diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken052.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken052.java index 5109f78c505..a7c0b61920a 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken052.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken052.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -110,11 +111,12 @@ public void deployTransferTokenContract() { user001Key, blockingStubFull); // deploy transferTokenContract - String contractName = "transferTokenContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken052_transferTokenContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken052_transferTokenContract"); + String filePath = "./src/test/resources/soliditycode/contractTrcToken052.sol"; + String contractName = "tokenTest"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); byte[] transferTokenContractAddress = PublicMethed .deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, 10000, assetAccountId.toStringUtf8(), diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken054.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken054.java index c75b2a8129c..ac35758c6b3 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken054.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken054.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.List; import java.util.Optional; import java.util.concurrent.TimeUnit; @@ -121,12 +122,14 @@ public void testTriggerTransferTokenContract() { logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " + devAssetCountBefore); - String contractName = "transferTokenContract"; + //String contractName = "transferTokenContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken054_transferTokenContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken054_transferTokenContract"); + String filePath = "./src/test/resources/soliditycode/contractTrcToken054.sol"; + String contractName = "tokenTest"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); String tokenId = assetAccountId.toStringUtf8(); long tokenValue = 100; @@ -141,6 +144,7 @@ public void testTriggerTransferTokenContract() { Optional infoById = PublicMethed .getTransactionInfoById(transferTokenTxid, blockingStubFull); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); @@ -226,6 +230,8 @@ public void testTriggerTransferTokenContract() { infoById = PublicMethed .getTransactionInfoById(triggerTxid, blockingStubFull); + logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + if (triggerTxid == null || infoById.get().getResultValue() != 0) { Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); } diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken055.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken055.java index b7c2ed2a331..4ea05fe33d7 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken055.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken055.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.List; import java.util.Optional; import java.util.concurrent.TimeUnit; @@ -125,11 +126,12 @@ public void triggerTransferTokenContract() { logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " + devAssetCountBefore); - String contractName = "transferTokenContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken055_transferTokenContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken055_transferTokenContract"); + String filePath = "./src/test/resources/soliditycode/contractTrcToken055.sol"; + String contractName = "tokenTest"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); String tokenId = assetAccountId.toStringUtf8(); long tokenValue = 100; long callValue = 0; @@ -143,6 +145,8 @@ public void triggerTransferTokenContract() { Optional infoById = PublicMethed .getTransactionInfoById(transferTokenTxid, blockingStubFull); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); } @@ -219,7 +223,7 @@ public void triggerTransferTokenContract() { callValue = 5; final String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, - "msgTokenValueAndTokenIdTest()", "#", false, callValue, + "msgTokenValueAndTokenIdTest()", "", false, callValue, 1000000000L, tokenId, tokenValue, user001Address, user001Key, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); @@ -244,6 +248,8 @@ public void triggerTransferTokenContract() { infoById = PublicMethed .getTransactionInfoById(triggerTxid, blockingStubFull); + logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + if (triggerTxid == null || infoById.get().getResultValue() != 0) { Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); } diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken060.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken060.java index 08690211207..9ffa0dd7d98 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken060.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken060.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.List; import java.util.Optional; import java.util.concurrent.TimeUnit; @@ -112,11 +113,12 @@ public void deployTransferTokenContract() { logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " + devAssetCountBefore); - String contractName = "transferTokenContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken060_transferTokenContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken060_transferTokenContract"); + String filePath = "./src/test/resources/soliditycode/contractTrcToken060.sol"; + String contractName = "tokenTest"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); String tokenId = assetAccountId.toStringUtf8(); long tokenValue = 0; long callValue = 5; @@ -129,6 +131,7 @@ public void deployTransferTokenContract() { Optional infoById = PublicMethed .getTransactionInfoById(transferTokenTxid, blockingStubFull); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); @@ -197,6 +200,8 @@ public void deployTransferTokenContract() { infoById = PublicMethed .getTransactionInfoById(triggerTxid, blockingStubFull); + logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + if (triggerTxid == null || infoById.get().getResultValue() != 0) { Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); } diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken061.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken061.java index 05fb0fdde06..078785c3f75 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken061.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken061.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.List; import java.util.Optional; import java.util.concurrent.TimeUnit; @@ -115,11 +116,12 @@ public void deployTransferTokenContract() { logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " + devAssetCountBefore); - String contractName = "transferTokenContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken061_transferTokenContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken061_transferTokenContract"); + String filePath = "./src/test/resources/soliditycode/contractTrcToken061.sol"; + String contractName = "tokenTest"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); String tokenId = Long.toString(Long.MAX_VALUE); long tokenValue = 0; long callValue = 10; @@ -132,6 +134,7 @@ public void deployTransferTokenContract() { Optional infoById = PublicMethed .getTransactionInfoById(transferTokenTxid, blockingStubFull); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); @@ -182,6 +185,8 @@ public void deployTransferTokenContract() { infoById = PublicMethed .getTransactionInfoById(triggerTxid, blockingStubFull); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + if (triggerTxid == null || infoById.get().getResultValue() != 0) { Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); } diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken064.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken064.java index c605aad41c3..f3c169adc47 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken064.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken064.java @@ -5,6 +5,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -137,11 +138,12 @@ public void test01DeployTransferTokenContract() { logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " + devAssetCountBefore); + String filePath = "./src/test/resources/soliditycode/contractTrcToken064.sol"; String contractName = "transferTokenContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken064_transferTokenContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken064_transferTokenContract"); + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); String transferTokenTxid = PublicMethed .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 0L, 0, 10000, @@ -151,6 +153,7 @@ public void test01DeployTransferTokenContract() { Optional infoById = PublicMethed .getTransactionInfoById(transferTokenTxid, blockingStubFull); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); @@ -205,11 +208,12 @@ public void test02DeployRevContract() { logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " + devAssetCountBefore); - String contractName = "resultContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken064_recieveTokenContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken064_recieveTokenContract"); + String filePath = "./src/test/resources/soliditycode/contractTrcToken064.sol"; + String contractName = "Result"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); String recieveTokenTxid = PublicMethed .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 0L, 100, 1000, assetAccountId.toStringUtf8(), @@ -218,6 +222,7 @@ public void test02DeployRevContract() { PublicMethed.waitProduceNextBlock(blockingStubFull); Optional infoById = PublicMethed .getTransactionInfoById(recieveTokenTxid, blockingStubFull); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); if (recieveTokenTxid == null || infoById.get().getResultValue() != 0) { Assert.fail("deploy receive failed with message: " + infoById.get().getResMessage()); @@ -293,19 +298,19 @@ public void test03TriggerContract() { + assetAccountId.toStringUtf8() + ", Count is " + receiveAssetBefore); Long callValue = Long.valueOf(0); - String param = "\"" + Base58.encode58Check(resultContractAddress) + "\""; String triggerTxid = PublicMethed.triggerContract(transferTokenContractAddress, "transferTokenTestValue0IdBigInteger(address)", param, false, callValue, 1000000000L, assetAccountId.toStringUtf8(), 2, user001Address, user001Key, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = PublicMethed .getTransactionInfoById(triggerTxid, blockingStubFull); + logger.info(infoById.get().getResMessage().toStringUtf8()); Assert.assertTrue(infoById.get().getResultValue() != 0); Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("BigInteger out of long range", + Assert.assertEquals("REVERT opcode executed", + //Assert.assertEquals("BigInteger out of long range", infoById.get().getResMessage().toStringUtf8()); //transfer to a normal account @@ -319,7 +324,8 @@ public void test03TriggerContract() { .getTransactionInfoById(triggerTxid, blockingStubFull); Assert.assertTrue(infoById.get().getResultValue() != 0); Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("BigInteger out of long range", + //Assert.assertEquals("BigInteger out of long range", + Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); String tokenId = Long.toString(Long.MIN_VALUE); @@ -339,7 +345,7 @@ public void test03TriggerContract() { Assert.assertTrue(infoById.get().getResultValue() != 0); Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("validateForSmartContract failure, not valid token id", + Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); tokenId = Long.toString(100_0000); @@ -359,7 +365,7 @@ public void test03TriggerContract() { Assert.assertTrue(infoById.get().getResultValue() != 0); Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("validateForSmartContract failure, not valid token id", + Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); tokenId = Long.toString(-1); @@ -379,7 +385,7 @@ public void test03TriggerContract() { Assert.assertTrue(infoById.get().getResultValue() != 0); Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("validateForSmartContract failure, not valid token id", + Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); tokenId = Long.toString(0); @@ -399,7 +405,7 @@ public void test03TriggerContract() { Assert.assertTrue(infoById.get().getResultValue() != 0); Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("validateForSmartContract failure, not valid token id", + Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); callValue = Long.valueOf(0); diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken066.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken066.java index cee9e16eb51..5c606951c4a 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken066.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken066.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.List; import java.util.Optional; import java.util.concurrent.TimeUnit; @@ -124,11 +125,12 @@ public void test01DeployTransferTokenContract() { logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " + devAssetCountBefore); + String filePath = "./src/test/resources/soliditycode/contractTrcToken066.sol"; String contractName = "transferTokenContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken066_transferTokenContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken066_transferTokenContract"); + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); String transferTokenTxid = PublicMethed .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 0L, 0, 10000, @@ -138,6 +140,7 @@ public void test01DeployTransferTokenContract() { Optional infoById = PublicMethed .getTransactionInfoById(transferTokenTxid, blockingStubFull); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); @@ -193,11 +196,12 @@ public void test02DeployRevContract() { logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " + devAssetCountBefore); - String contractName = "resultContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken066_recieveTokenContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken066_recieveTokenContract"); + String filePath = "./src/test/resources/soliditycode/contractTrcToken066.sol"; + String contractName = "Result"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); String recieveTokenTxid = PublicMethed .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, 0L, 100, 1000, assetAccountId.toStringUtf8(), @@ -206,6 +210,8 @@ public void test02DeployRevContract() { PublicMethed.waitProduceNextBlock(blockingStubFull); Optional infoById = PublicMethed .getTransactionInfoById(recieveTokenTxid, blockingStubFull); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + if (recieveTokenTxid == null || infoById.get().getResultValue() != 0) { Assert.fail("deploy receive failed with message: " + infoById.get().getResMessage()); } @@ -296,6 +302,7 @@ public void test03TriggerContract() { Optional infoById = PublicMethed .getTransactionInfoById(triggerTxid, blockingStubFull); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); TransactionInfo transactionInfo = infoById.get(); if (triggerTxid == null || infoById.get().getResultValue() != 0) { @@ -392,6 +399,8 @@ public void test04TriggerTokenBalanceContract() { Optional infoById = PublicMethed.getTransactionInfoById(triggerTxid, blockingStubFull); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + if (triggerTxid == null || infoById.get().getResultValue() != 0) { Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); } diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken067.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken067.java index 98512298448..a8e06dd8b19 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken067.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken067.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.List; import java.util.Optional; import java.util.concurrent.TimeUnit; @@ -125,11 +126,12 @@ public void test01DeployTransferTokenContract() { logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " + devAssetCountBefore); + String filePath = "./src/test/resources/soliditycode/contractTrcToken067.sol"; String contractName = "transferTokenContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken067_transferTokenContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken067_transferTokenContract"); + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); String transferTokenTxid = PublicMethed .deployContractAndGetTransactionInfoById(contractName, abi, code, "", @@ -140,6 +142,7 @@ public void test01DeployTransferTokenContract() { Optional infoById = PublicMethed .getTransactionInfoById(transferTokenTxid, blockingStubFull); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); @@ -195,11 +198,12 @@ public void test02DeployRevContract() { logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " + devAssetCountBefore); - String contractName = "resultContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken067_recieveTokenContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken067_recieveTokenContract"); + String filePath = "./src/test/resources/soliditycode/contractTrcToken067.sol"; + String contractName = "Result"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); String recieveTokenTxid = PublicMethed .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, @@ -209,6 +213,7 @@ public void test02DeployRevContract() { PublicMethed.waitProduceNextBlock(blockingStubFull); Optional infoById = PublicMethed .getTransactionInfoById(recieveTokenTxid, blockingStubFull); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); if (recieveTokenTxid == null || infoById.get().getResultValue() != 0) { Assert.fail("deploy receive failed with message: " + infoById.get().getResMessage()); @@ -301,6 +306,7 @@ public void test03TriggerContract() { PublicMethed.waitProduceNextBlock(blockingStubFull); Optional infoById = PublicMethed .getTransactionInfoById(triggerTxid, blockingStubFull); + logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); if (triggerTxid == null || infoById.get().getResultValue() != 0) { Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); @@ -395,6 +401,8 @@ public void test04TriggerTokenBalanceContract() { PublicMethed.waitProduceNextBlock(blockingStubFull); Optional infoById = PublicMethed.getTransactionInfoById(triggerTxid, blockingStubFull); + logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + if (triggerTxid == null || infoById.get().getResultValue() != 0) { Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); } diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken073.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken073.java index cbd3c154abb..2b1bd92b09a 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken073.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken073.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -113,11 +114,12 @@ public void testTokenBalanceContract() { logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " + devAssetCountBefore); - String contractName = "transferTokenContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken073_transferTokenContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken073_transferTokenContract"); + String filePath = "./src/test/resources/soliditycode/contractTrcToken073.sol"; + String contractName = "Dest"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); String tokenId = assetAccountId.toStringUtf8(); long tokenValue = 100; long callValue = 5; @@ -130,6 +132,7 @@ public void testTokenBalanceContract() { Optional infoById = PublicMethed .getTransactionInfoById(transferTokenTxid, blockingStubFull); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); @@ -185,6 +188,8 @@ public void testTokenBalanceContract() { PublicMethed.waitProduceNextBlock(blockingStubFull); infoById = PublicMethed .getTransactionInfoById(triggerTxid, blockingStubFull); + logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + if (triggerTxid == null || infoById.get().getResultValue() != 0) { Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); } @@ -222,6 +227,8 @@ public void testTokenBalanceContract() { infoById = PublicMethed .getTransactionInfoById(triggerTxid, blockingStubFull); + logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + if (triggerTxid == null || infoById.get().getResultValue() != 0) { Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); } @@ -251,6 +258,8 @@ public void testTokenBalanceContract() { infoById = PublicMethed .getTransactionInfoById(triggerTxid, blockingStubFull); + logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + if (triggerTxid == null || infoById.get().getResultValue() != 0) { Assert.fail("transaction failed with message: " + infoById.get().getResMessage()); } diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken075.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken075.java index 259b425c941..75343e7687e 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken075.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken075.java @@ -5,6 +5,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -116,11 +117,12 @@ public void testTokenBalanceContract() { logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " + devAssetCountBefore); - String contractName = "transferTokenContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken075_transferTokenContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken075_transferTokenContract"); + String filePath = "./src/test/resources/soliditycode/contractTrcToken075.sol"; + String contractName = "Dest"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); String tokenId = assetAccountId.toStringUtf8(); long tokenValue = 100; long callValue = 5; @@ -133,6 +135,7 @@ public void testTokenBalanceContract() { PublicMethed.waitProduceNextBlock(blockingStubFull); Optional infoById = PublicMethed .getTransactionInfoById(transferTokenTxid, blockingStubFull); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); if (transferTokenTxid == null || infoById.get().getResultValue() != 0) { Assert.fail("deploy transaction failed with message: " + infoById.get().getResMessage()); @@ -190,9 +193,11 @@ public void testTokenBalanceContract() { PublicMethed.waitProduceNextBlock(blockingStubFull); infoById = PublicMethed .getTransactionInfoById(triggerTxid, blockingStubFull); + logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + Assert.assertTrue(infoById.get().getResultValue() != 0); Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("validateForSmartContract failure, not valid token id", + Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); PublicMethed.waitProduceNextBlock(blockingStubFull); @@ -205,9 +210,11 @@ public void testTokenBalanceContract() { PublicMethed.waitProduceNextBlock(blockingStubFull); infoById = PublicMethed .getTransactionInfoById(triggerTxid, blockingStubFull); + logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + Assert.assertTrue(infoById.get().getResultValue() != 0); Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("validateForSmartContract failure, not valid token id", + Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); PublicMethed.waitProduceNextBlock(blockingStubFull); @@ -221,9 +228,11 @@ public void testTokenBalanceContract() { infoById = PublicMethed .getTransactionInfoById(triggerTxid, blockingStubFull); + logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + Assert.assertTrue(infoById.get().getResultValue() != 0); Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("validateForSmartContract failure, not valid token id", + Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); PublicMethed.waitProduceNextBlock(blockingStubFull); @@ -235,9 +244,11 @@ public void testTokenBalanceContract() { blockingStubFull); infoById = PublicMethed .getTransactionInfoById(triggerTxid, blockingStubFull); + logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + Assert.assertTrue(infoById.get().getResultValue() != 0); Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("validateForSmartContract failure, not valid token id", + Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); PublicMethed.waitProduceNextBlock(blockingStubFull); @@ -249,9 +260,11 @@ public void testTokenBalanceContract() { infoById = PublicMethed .getTransactionInfoById(triggerTxid, blockingStubFull); + logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + Assert.assertTrue(infoById.get().getResultValue() != 0); Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("BigInteger out of long range", + Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); PublicMethed.waitProduceNextBlock(blockingStubFull); @@ -261,12 +274,14 @@ public void testTokenBalanceContract() { 1000000000L, "0", 0, dev001Address, dev001Key, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - infoById = PublicMethed .getTransactionInfoById(triggerTxid, blockingStubFull); + logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + Assert.assertTrue(infoById.get().getResultValue() != 0); Assert.assertEquals(FAILED, infoById.get().getResult()); - Assert.assertEquals("BigInteger out of long range", + //Assert.assertEquals("BigInteger out of long range", + Assert.assertEquals("REVERT opcode executed", infoById.get().getResMessage().toStringUtf8()); // unfreeze resource diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken076.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken076.java index d87dfc7700c..4d216784749 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken076.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken076.java @@ -2,6 +2,7 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -81,14 +82,22 @@ public void testDeployTransferTokenContract() { PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName = "originTest"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken076_originTest"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken076_originTest"); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, testKeyForGrammarAddress, - grammarAddress, blockingStubFull); + String filePath = "./src/test/resources/soliditycode/contractTrcToken076.sol"; + String contractName = "Test"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + String txid = PublicMethed + .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, + 0L, 100, null, testKeyForGrammarAddress, + grammarAddress, blockingStubFull); + Optional infoById = PublicMethed + .getTransactionInfoById(txid, blockingStubFull); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + + contractAddress = infoById.get().getContractAddress().toByteArray(); + PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.triggerContract(contractAddress, @@ -97,15 +106,15 @@ public void testDeployTransferTokenContract() { PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String txid = ""; txid = PublicMethed.triggerContract(contractAddress, "getResult1()", "#", false, 0, maxFeeLimit, grammarAddress, testKeyForGrammarAddress, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - Optional infoById = null; infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + logger.info("infoById:" + infoById); Long returnnumber = ByteArray.toLong(ByteArray.fromHexString(ByteArray.toHexString( infoById.get().getContractResult(0).toByteArray()))); @@ -119,6 +128,8 @@ public void testDeployTransferTokenContract() { PublicMethed.waitProduceNextBlock(blockingStubFull); infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); + logger.info("Deploy energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + logger.info("-------------------------"); logger.info("infoById:" + infoById); diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken077.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken077.java index 5f0b110fb52..e4adf390894 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken077.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken077.java @@ -2,6 +2,7 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -78,14 +79,23 @@ public void testAddress001() { PublicMethed .sendcoin(grammarAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, blockingStubFull); - String contractName = "AddressTest"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken077_AddressTest"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken077_AddressTest"); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, testKeyForGrammarAddress, - grammarAddress, blockingStubFull); + + String filePath = "./src/test/resources/soliditycode/contractTrcToken077.sol"; + String contractName = "trcToken077"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + + String deployTxid = PublicMethed + .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, + 0L, 100, null, testKeyForGrammarAddress, + grammarAddress, blockingStubFull); + Optional deployInfo = PublicMethed + .getTransactionInfoById(deployTxid, blockingStubFull); + contractAddress = deployInfo.get().getContractAddress().toByteArray(); + logger.info("Deploy energy is " + deployInfo.get().getReceipt().getEnergyUsageTotal()); + String txid = ""; txid = PublicMethed.triggerContract(contractAddress, "addressTest()", "#", false, @@ -93,7 +103,7 @@ public void testAddress001() { Optional infoById = null; infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); logger.info("infoById:" + infoById); - + logger.info("Trigger energy is " + infoById.get().getReceipt().getEnergyUsageTotal()); } @@ -105,14 +115,21 @@ public void testAddress002() { PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName = "AddressTest"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken077_AddressTest1"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken077_AddressTest1"); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 0L, 100, null, testKeyForGrammarAddress, - grammarAddress, blockingStubFull); + String filePath = "./src/test/resources/soliditycode/contractTrcToken077.sol"; + String contractName = "trcToken077"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + + String deploytxid = PublicMethed + .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, + 0L, 100, null, testKeyForGrammarAddress, + grammarAddress, blockingStubFull); + Optional deployById = PublicMethed + .getTransactionInfoById(deploytxid, blockingStubFull); + contractAddress = deployById.get().getContractAddress().toByteArray(); + logger.info("infoById:" + deployById); PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken078.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken078.java index 2e7ee99b105..c6d2be29a0c 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken078.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken078.java @@ -3,6 +3,7 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Optional; import java.util.concurrent.TimeUnit; @@ -12,12 +13,14 @@ import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; +import org.tron.api.GrpcAPI.AccountResourceMessage; import org.tron.api.WalletGrpc; import org.tron.api.WalletSolidityGrpc; import org.tron.common.crypto.ECKey; import org.tron.common.utils.ByteArray; import org.tron.common.utils.Utils; import org.tron.core.Wallet; +import org.tron.protos.Protocol.Account; import org.tron.protos.Protocol.TransactionInfo; import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; @@ -53,6 +56,7 @@ public class ContractTrcToken078 { ECKey ecKey1 = new ECKey(Utils.getRandom()); byte[] internalTxsAddress = ecKey1.getAddress(); String testKeyForinternalTxsAddress = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); + String priKey = ByteArray.toHexString(ecKey1.getPrivKeyBytes()); @BeforeSuite @@ -84,43 +88,69 @@ public void testOriginCall001() { .sendcoin(internalTxsAddress, 100000000000L, testNetAccountAddress, testNetAccountKey, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); + PublicMethed + .freezeBalanceGetEnergy(internalTxsAddress, 10000000000L, 0L, 1, priKey, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName = "AAContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken078_AddressTest1"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken078_AddressTest1"); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); - PublicMethed.waitProduceNextBlock(blockingStubFull); + String filePath = "./src/test/resources/soliditycode/contractTrcToken078.sol"; + String contractName = "callerContract"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + + String txid = PublicMethed + .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, + 1000000L, 100, null, testKeyForinternalTxsAddress, + internalTxsAddress, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName1 = "BContract"; - String code1 = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken078_AddressTest2"); - String abi1 = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken078_AddressTest2"); - byte[] contractAddress1 = PublicMethed - .deployContract(contractName1, abi1, code1, "", maxFeeLimit, + Optional infoById = PublicMethed + .getTransactionInfoById(txid, blockingStubFull); + logger.info("infoById : " + infoById); + contractAddress = infoById.get().getContractAddress().toByteArray(); + + String filePath1 = "./src/test/resources/soliditycode/contractTrcToken078.sol"; + String contractName1 = "calledContract"; + HashMap retMap1 = PublicMethed.getBycodeAbi(filePath1, contractName1); + + String code1 = retMap1.get("byteCode").toString(); + String abi1 = retMap1.get("abI").toString(); + + txid = PublicMethed + .deployContractAndGetTransactionInfoById(contractName1, abi1, code1, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, internalTxsAddress, blockingStubFull); + infoById = PublicMethed + .getTransactionInfoById(txid, blockingStubFull); + logger.info("infoById : " + infoById); + byte[] contractAddress1; + contractAddress1 = infoById.get().getContractAddress().toByteArray(); + PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName2 = "CContract"; - String code2 = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken078_AddressTest3"); - String abi2 = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken078_AddressTest3"); - byte[] contractAddress2 = PublicMethed - .deployContract(contractName2, abi2, code2, "", maxFeeLimit, + + String filePath2 = "./src/test/resources/soliditycode/contractTrcToken078.sol"; + String contractName2 = "c"; + HashMap retMap2 = PublicMethed.getBycodeAbi(filePath2, contractName2); + + String code2 = retMap2.get("byteCode").toString(); + String abi2 = retMap2.get("abI").toString(); + + txid = PublicMethed + .deployContractAndGetTransactionInfoById(contractName2, abi2, code2, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, internalTxsAddress, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); + + infoById = PublicMethed + .getTransactionInfoById(txid, blockingStubFull); + byte[] contractAddress2 = infoById.get().getContractAddress().toByteArray(); + logger.info("infoById : " + infoById); + String initParmes = "\"" + Base58.encode58Check(contractAddress1) + "\",\"" + Base58.encode58Check(contractAddress2) + "\""; @@ -133,6 +163,12 @@ public void testOriginCall001() { PublicMethed.waitProduceNextBlock(blockingStubFull); Optional infoById2 = null; infoById2 = PublicMethed.getTransactionInfoById(txid2, blockingStubFull); + logger.info("Trigger InfobyId: " + infoById2); + Account info1 = PublicMethed.queryAccount(internalTxsAddress, blockingStubFull); + AccountResourceMessage resourceInfo1 = PublicMethed.getAccountResource(internalTxsAddress, + blockingStubFull); + logger.info("getEnergyUsed " + resourceInfo1.getEnergyUsed()); + logger.info("getEnergyLimit " + resourceInfo1.getEnergyLimit()); Assert.assertTrue(infoById2.get().getResultValue() == 0); @@ -145,42 +181,63 @@ public void testOriginDelegatecall001() { blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName = "AAContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken078_AddressTest4"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken078_AddressTest4"); - contractAddress = PublicMethed.deployContract(contractName, abi, code, "", maxFeeLimit, - 1000000L, 100, null, testKeyForinternalTxsAddress, - internalTxsAddress, blockingStubFull); + String filePath = "./src/test/resources/soliditycode/contractTrcToken078.sol"; + String contractName = "callerContract"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + + String txid = PublicMethed + .deployContractAndGetTransactionInfoById(contractName, abi, code, "", maxFeeLimit, + 1000000L, 100, null, testKeyForinternalTxsAddress, + internalTxsAddress, blockingStubFull); + Optional infoById = PublicMethed + .getTransactionInfoById(txid, blockingStubFull); + logger.info("infoById : " + infoById); + contractAddress = infoById.get().getContractAddress().toByteArray(); + PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName1 = "BContract"; - String code1 = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken078_AddressTest5"); - String abi1 = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken078_AddressTest5"); - byte[] contractAddress1 = PublicMethed - .deployContract(contractName1, abi1, code1, "", maxFeeLimit, + String filePath1 = "./src/test/resources/soliditycode/contractTrcToken078.sol"; + String contractName1 = "calledContract"; + HashMap retMap1 = PublicMethed.getBycodeAbi(filePath1, contractName1); + + String code1 = retMap1.get("byteCode").toString(); + String abi1 = retMap1.get("abI").toString(); + txid = PublicMethed + .deployContractAndGetTransactionInfoById(contractName1, abi1, code1, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, internalTxsAddress, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); - String contractName2 = "CContract"; - String code2 = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken078_AddressTest6"); - String abi2 = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken078_AddressTest6"); - byte[] contractAddress2 = PublicMethed - .deployContract(contractName2, abi2, code2, "", maxFeeLimit, + infoById = PublicMethed + .getTransactionInfoById(txid, blockingStubFull); + logger.info("infoById : " + infoById); + byte[] contractAddress1; + contractAddress1 = infoById.get().getContractAddress().toByteArray(); + + String filePath2 = "./src/test/resources/soliditycode/contractTrcToken078.sol"; + String contractName2 = "c"; + HashMap retMap2 = PublicMethed.getBycodeAbi(filePath2, contractName2); + + String code2 = retMap2.get("byteCode").toString(); + String abi2 = retMap2.get("abI").toString(); + txid = PublicMethed + .deployContractAndGetTransactionInfoById(contractName2, abi2, code2, "", maxFeeLimit, 1000000L, 100, null, testKeyForinternalTxsAddress, internalTxsAddress, blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); PublicMethed.waitProduceNextBlock(blockingStubFull); + infoById = PublicMethed + .getTransactionInfoById(txid, blockingStubFull); + logger.info("infoById : " + infoById); + byte[] contractAddress2 = infoById.get().getContractAddress().toByteArray(); + String initParmes = "\"" + Base58.encode58Check(contractAddress1) + "\",\"" + Base58.encode58Check(contractAddress2) + "\""; @@ -193,6 +250,8 @@ public void testOriginDelegatecall001() { PublicMethed.waitProduceNextBlock(blockingStubFull); Optional infoById2 = null; infoById2 = PublicMethed.getTransactionInfoById(txid2, blockingStubFull); + logger.info("infoById : " + infoById2); + Assert.assertTrue(infoById2.get().getResultValue() == 0); diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken079.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken079.java index 515b7956843..79d596385f1 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken079.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken079.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.List; import java.util.Optional; import java.util.concurrent.TimeUnit; @@ -121,11 +122,12 @@ public void triggerTransferTokenContract() { logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " + devAssetCountBefore); - String contractName = "transferTokenContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken0552_transferTokenContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken0552_transferTokenContract"); + String filePath = "./src/test/resources/soliditycode/contractTrcToken079.sol"; + String contractName = "tokenTest"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); + String tokenId = assetAccountId.toStringUtf8(); long tokenValue = 100; long callValue = 0; diff --git a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken080.java b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken080.java index 56a286bd5ef..31a550bf082 100644 --- a/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken080.java +++ b/src/test/java/stest/tron/wallet/dailybuild/trctoken/ContractTrcToken080.java @@ -3,6 +3,7 @@ import com.google.protobuf.ByteString; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import java.util.HashMap; import java.util.List; import java.util.Optional; import java.util.concurrent.TimeUnit; @@ -115,11 +116,11 @@ public void deployTransferTokenContract() { logger.info("before AssetId: " + assetAccountId.toStringUtf8() + ", devAssetCountBefore: " + devAssetCountBefore); - String contractName = "transferTokenContract"; - String code = Configuration.getByPath("testng.conf") - .getString("code.code_ContractTrcToken0612_transferTokenContract"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_ContractTrcToken0612_transferTokenContract"); + String filePath = "./src/test/resources/soliditycode/contractTrcToken080.sol"; + String contractName = "tokenTest"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); String tokenId = Long.toString(0); long tokenValue = 0; long callValue = 10; diff --git a/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign004.java b/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign004.java index 13ff7565034..594bd164881 100644 --- a/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign004.java +++ b/src/test/java/stest/tron/wallet/mutisign/WalletTestMutiSign004.java @@ -4,6 +4,7 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import java.util.ArrayList; +import java.util.HashMap; import java.util.Optional; import java.util.Random; import java.util.concurrent.TimeUnit; @@ -151,11 +152,13 @@ public void testMutiSignForSmartContract() { randNum = rand.nextInt(4000); Long maxFeeLimit = 1000000000L; - String contractName = "StorageAndCpu" + Integer.toString(randNum); - String code = Configuration.getByPath("testng.conf") - .getString("code.code_TestStorageAndCpu_storageAndCpu"); - String abi = Configuration.getByPath("testng.conf") - .getString("abi.abi_TestStorageAndCpu_storageAndCpu"); + //String contractName = "StorageAndCpu" + Integer.toString(randNum); + String filePath = "./src/test/resources/soliditycode/walletTestMutiSign004.sol"; + String contractName = "timeoutTest"; + HashMap retMap = PublicMethed.getBycodeAbi(filePath, contractName); + + String code = retMap.get("byteCode").toString(); + String abi = retMap.get("abI").toString(); byte[] contractAddress = PublicMethedForMutiSign.deployContract(contractName, abi, code, "", maxFeeLimit, 0L, 100, null, ownerKey, ownerAddress, blockingStubFull, ownerKeyString); @@ -169,8 +172,10 @@ public void testMutiSignForSmartContract() { "testUseCpu(uint256)", initParmes, false, 0, maxFeeLimit, ownerAddress, ownerKey, blockingStubFull, ownerKeyString); PublicMethed.waitProduceNextBlock(blockingStubFull); - PublicMethed.getTransactionById(txid, blockingStubFull); infoById = PublicMethed.getTransactionInfoById(txid, blockingStubFull); + logger.info("Txid is " + txid); + logger.info("Trigger energytotal is " + infoById.get().getReceipt().getEnergyUsageTotal()); + Assert.assertTrue(infoById.get().getBlockNumber() > 0); PublicMethedForMutiSign.updateSettingWithPermissionId(contractAddress, 50, ownerKey, ownerAddress, 0, blockingStubFull, ownerKeyString); diff --git a/src/test/java/stest/tron/wallet/onlinestress/ContractEvent001.java b/src/test/java/stest/tron/wallet/onlinestress/ContractEvent001.java index 026356dc4fb..f82f4be4809 100644 --- a/src/test/java/stest/tron/wallet/onlinestress/ContractEvent001.java +++ b/src/test/java/stest/tron/wallet/onlinestress/ContractEvent001.java @@ -23,9 +23,11 @@ import org.tron.common.utils.Utils; import org.tron.core.Wallet; import org.tron.protos.Protocol.SmartContract; +import org.zeromq.ZMQ; import stest.tron.wallet.common.client.Configuration; import stest.tron.wallet.common.client.Parameter.CommonConstant; import stest.tron.wallet.common.client.utils.PublicMethed; +import zmq.ZMQ.Event; @Slf4j public class ContractEvent001 { @@ -249,10 +251,44 @@ public void test1ContractEventAndLog() { "triggerEventBytes()", "#", false, 0, maxFeeLimit, event001Address, event001Key, blockingStubFull); logger.info(txid); + } + + @Test(enabled = true, description = "Subscribe event client") + public void testEnergyCostDetail() { + ZMQ.Context context = ZMQ.context(1); + ZMQ.Socket req = context.socket(ZMQ.SUB); + + req.subscribe("blockTrigger"); + req.subscribe("transactionTrigger"); + req.subscribe("contractLogTrigger"); + req.subscribe("contractEventTrigger"); + req.monitor("inproc://reqmoniter", ZMQ.EVENT_CONNECTED | ZMQ.EVENT_DISCONNECTED); + final ZMQ.Socket moniter = context.socket(ZMQ.PAIR); + moniter.connect("inproc://reqmoniter"); + new Thread(new Runnable() { + public void run() { + while (true) { + Event event = Event.read(moniter.base()); + System.out.println(event.event + " " + event.addr); + } + } + + }).start(); + req.connect("tcp://47.94.197.215:55555"); + req.setReceiveTimeOut(10000); + + while (true) { + byte[] message = req.recv(); + if (message != null) { + System.out.println("receive : " + new String(message)); + } + } + } + /** * constructor. */ diff --git a/src/test/java/stest/tron/wallet/onlinestress/DelayTransactionStress.java b/src/test/java/stest/tron/wallet/onlinestress/DelayTransactionStress.java new file mode 100644 index 00000000000..69f53a745b7 --- /dev/null +++ b/src/test/java/stest/tron/wallet/onlinestress/DelayTransactionStress.java @@ -0,0 +1,359 @@ +package stest.tron.wallet.onlinestress; + +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import java.util.Optional; +import java.util.concurrent.TimeUnit; +import lombok.extern.slf4j.Slf4j; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeSuite; +import org.testng.annotations.Test; +import org.tron.api.WalletGrpc; +import org.tron.common.crypto.ECKey; +import org.tron.common.utils.ByteArray; +import org.tron.common.utils.Utils; +import org.tron.core.Wallet; +//import org.tron.protos.Protocol.DeferredTransaction; +import org.tron.protos.Protocol.Transaction; +import org.tron.protos.Protocol.TransactionInfo; +import stest.tron.wallet.common.client.Configuration; +import stest.tron.wallet.common.client.Parameter.CommonConstant; +import stest.tron.wallet.common.client.utils.Base58; +import stest.tron.wallet.common.client.utils.PublicMethed; +import stest.tron.wallet.common.client.utils.Sha256Hash; + +@Slf4j +public class DelayTransactionStress { + + private final String testKey002 = Configuration.getByPath("testng.conf") + .getString("foundationAccount.key1"); + private final String testKey003 = Configuration.getByPath("testng.conf") + .getString("foundationAccount.key2"); + private final byte[] fromAddress = PublicMethed.getFinalAddress(testKey002); + private final byte[] toAddress = PublicMethed.getFinalAddress(testKey003); + + private ManagedChannel channelFull = null; + private WalletGrpc.WalletBlockingStub blockingStubFull = null; + + private String fullnode = Configuration.getByPath("testng.conf").getStringList("fullnode.ip.list") + .get(0); + private Long delayTransactionFee = Configuration.getByPath("testng.conf") + .getLong("defaultParameter.delayTransactionFee"); + + + public static final long MAX_DEFERRED_TRANSACTION_DELAY_SECONDS = 45 * 24 * 3_600L; //45 days + Optional infoById = null; + //Optional deferredTransactionById = null; + Optional getTransactionById = null; + + + ECKey ecKey = new ECKey(Utils.getRandom()); + byte[] delayAccount1Address = ecKey.getAddress(); + String delayAccount1Key = ByteArray.toHexString(ecKey.getPrivKeyBytes()); + + ECKey ecKey2 = new ECKey(Utils.getRandom()); + byte[] delayAccount2Address = ecKey2.getAddress(); + String delayAccount2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); + + ECKey ecKey3 = new ECKey(Utils.getRandom()); + byte[] receiverAccountAddress = ecKey3.getAddress(); + String receiverAccountKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); + + ECKey ecKey4 = new ECKey(Utils.getRandom()); + byte[] delayAccount3Address = ecKey4.getAddress(); + String delayAccount3Key = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); + + ECKey ecKey5 = new ECKey(Utils.getRandom()); + byte[] receiverAccount4Address = ecKey5.getAddress(); + String receiverAccount4Key = ByteArray.toHexString(ecKey5.getPrivKeyBytes()); + + @BeforeSuite + public void beforeSuite() { + Wallet wallet = new Wallet(); + Wallet.setAddressPreFixByte(CommonConstant.ADD_PRE_FIX_BYTE_MAINNET); + } + + /** + * constructor. + */ + + @BeforeClass(enabled = true) + public void beforeClass() { + channelFull = ManagedChannelBuilder.forTarget(fullnode) + .usePlaintext(true) + .build(); + blockingStubFull = WalletGrpc.newBlockingStub(channelFull); + } + + @Test(enabled = true, threadPoolSize = 30, invocationCount = 2000) + public void test1DelaySendcoinStress() { + String txid = ""; + Integer i = 0; + String cancelId = ""; + while (i++ <= 10000000) { + ECKey ecKey2 = new ECKey(Utils.getRandom()); + byte[] delayAccount2Address = ecKey2.getAddress(); + String delayAccount2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); + + txid = PublicMethed.sendcoinDelayedGetTxid(delayAccount2Address, 1L, 20,fromAddress, + testKey002, blockingStubFull); + //PublicMethed.waitProduceNextBlock(blockingStubFull); + if (i % 20 == 0) { + cancelId = txid; + //PublicMethed.sendcoin(delayAccount2Address,1L,fromAddress,testKey002,blockingStubFull); + } + if (i % 39 == 0) { + PublicMethed.cancelDeferredTransactionById(cancelId,fromAddress,testKey002, + blockingStubFull); + PublicMethed.sendcoin(delayAccount2Address,1L,fromAddress,testKey002, + blockingStubFull); + } + + } + + + } + + /* @Test(enabled = true, description = "Get deferred transaction by id") + public void test2getDeferredTransactionByid() { + //get account + ECKey ecKey2 = new ECKey(Utils.getRandom()); + byte[] delayAccount2Address = ecKey2.getAddress(); + String delayAccount2Key = ByteArray.toHexString(ecKey2.getPrivKeyBytes()); + + ecKey3 = new ECKey(Utils.getRandom()); + receiverAccountAddress = ecKey3.getAddress(); + receiverAccountKey = ByteArray.toHexString(ecKey3.getPrivKeyBytes()); + PublicMethed.printAddress(delayAccount2Key); + PublicMethed.printAddress(receiverAccountKey); + + //Pre sendcoin to the test account + Assert.assertTrue(PublicMethed.sendcoin(delayAccount2Address, 100000000L,fromAddress, + testKey002, blockingStubFull)); + Assert.assertTrue(PublicMethed.sendcoin(receiverAccountAddress, 10L,fromAddress, + testKey002, blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + //Do delay send coin transaction. + Long delaySecond = 10L; + Long sendCoinAmout = 100L; + + //Query balance before send coin. + Long deplayAccountBeforeBalance = PublicMethed.queryAccount(delayAccount2Address, + blockingStubFull).getBalance(); + Long recevierAccountBeforeBalance = PublicMethed.queryAccount(receiverAccountAddress, + blockingStubFull).getBalance(); + logger.info("deplayAccountBeforeBalance " + deplayAccountBeforeBalance); + logger.info("recevierAccountBeforeBalance " + recevierAccountBeforeBalance); + String txid = PublicMethed.sendcoinDelayedGetTxid(receiverAccountAddress, sendCoinAmout, + delaySecond,delayAccount2Address, + delayAccount2Key, blockingStubFull); + + PublicMethed.waitProduceNextBlock(blockingStubFull); + + //Query balance when pre-sendcoin stage. + Long deplayAccountInDelayBalance = PublicMethed.queryAccount(delayAccount2Address, + blockingStubFull).getBalance(); + Long recevierAccountInDelayalance = PublicMethed.queryAccount(receiverAccountAddress, + blockingStubFull).getBalance(); + logger.info("deplayAccountInDelayBalance " + deplayAccountInDelayBalance); + logger.info("recevierAccountInDelayalance " + recevierAccountInDelayalance); + Assert.assertTrue(recevierAccountBeforeBalance == recevierAccountInDelayalance); + //Assert.assertTrue(); + + + deferredTransactionById = PublicMethed.getDeferredTransactionById(txid,blockingStubFull); + DeferredTransaction transaction = deferredTransactionById.get(); + String finalTxid = ByteArray.toHexString(Sha256Hash.hash(transaction.getTransaction() + .getRawData().toByteArray())); + PublicMethed.getDeferredTransactionById(finalTxid,blockingStubFull); + logger.info(finalTxid); + //logger.info("receiver address is " + Base58.encode58Check(transaction + .getReceiverAddress().toByteArray())); + Assert.assertTrue(Base58.encode58Check(transaction.getReceiverAddress().toByteArray()) + .equalsIgnoreCase(PublicMethed.getAddressString(receiverAccountKey))); + //logger.info("sender address is " + Base58.encode58Check(transaction + .getSenderAddress().toByteArray())); + Assert.assertTrue(Base58.encode58Check(transaction.getSenderAddress().toByteArray()) + .equalsIgnoreCase(PublicMethed.getAddressString(delayAccount2Key))); + // logger.info("delaySeconds is " + transaction.getDelaySeconds()); + Assert.assertTrue(delaySecond == transaction.getDelaySeconds()); + //logger.info("DelayUntil " + transaction.getDelayUntil()); + Assert.assertTrue(transaction.getDelayUntil() > System.currentTimeMillis()); + //logger.info("Expiration " + transaction.getExpiration()); + Assert.assertTrue(transaction.getExpiration() > System.currentTimeMillis()); + //logger.info("PublishTime " + transaction.getPublishTime()); + Assert.assertTrue(transaction.getPublishTime() < System.currentTimeMillis()); + //Assert.assertTrue(transaction.getDelayUntil() + 60000 == transaction.getExpiration()); + getTransactionById = PublicMethed.getTransactionById(txid, blockingStubFull); + logger.info("transaction stage in txid is " + getTransactionById.get().getRawData() + .getDeferredStage().getStage()); + + Assert.assertTrue(getTransactionById.get().getRawData().getDeferredStage().getStage() == 1); + getTransactionById = PublicMethed.getTransactionById(finalTxid, blockingStubFull); + logger.info("transaction stage in final id is " + getTransactionById + .get().getRawData().getDeferredStage().getStage()); + Assert.assertTrue(getTransactionById.get().getRawData().getDeferredStage().getStage() == 0); + + PublicMethed.waitProduceNextBlock(blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + PublicMethed.getDeferredTransactionById(finalTxid,blockingStubFull); + deferredTransactionById = PublicMethed.getDeferredTransactionById(txid,blockingStubFull); + finalTxid = ByteArray.toHexString(Sha256Hash.hash(transaction.getTransaction() + .getRawData().toByteArray())); + transaction = deferredTransactionById.get(); + logger.info(finalTxid); + //logger.info("receiver address is " + Base58.encode58Check(transaction.getReceiverAddress() + .toByteArray())); + //logger.info("receiver address is " + Base58.encode58Check(transaction.getSenderAddress() + .toByteArray())); + //logger.info("delaySeconds is " + transaction.getDelaySeconds()); + //logger.info("DelayUntil " + transaction.getDelayUntil()); + //logger.info("Expiration " + transaction.getExpiration()); + //logger.info("PublishTime " + transaction.getPublishTime()); + getTransactionById = PublicMethed.getTransactionById(txid, blockingStubFull); + logger.info("transaction stage in txid is " + getTransactionById.get().getRawData() + .getDeferredStage().getStage()); + getTransactionById = PublicMethed.getTransactionById(finalTxid, blockingStubFull); + logger.info("transaction stage in final id is " + getTransactionById.get().getRawData() + .getDeferredStage().getStage()); + + + + //Query balance after delay send coin. + Long deplayAccountAfterBalance = PublicMethed.queryAccount(delayAccount2Address, + blockingStubFull).getBalance(); + Long recevierAccountAfterDelayalance = PublicMethed.queryAccount(receiverAccountAddress, + blockingStubFull).getBalance(); + logger.info("deplayAccountAfterBalance " + deplayAccountAfterBalance); + logger.info("recevierAccountAfterDelayalance " + recevierAccountAfterDelayalance); + + Assert.assertTrue(deplayAccountBeforeBalance - deplayAccountAfterBalance == sendCoinAmout + + 100000L); + Assert.assertTrue(recevierAccountAfterDelayalance - recevierAccountBeforeBalance + == sendCoinAmout); + + }*/ + + @Test(enabled = true, description = "Delay send coin") + public void test3DelaySendCoin() { + ecKey4 = new ECKey(Utils.getRandom()); + delayAccount3Address = ecKey4.getAddress(); + delayAccount3Key = ByteArray.toHexString(ecKey4.getPrivKeyBytes()); + PublicMethed.printAddress(delayAccount3Key); + + ecKey5 = new ECKey(Utils.getRandom()); + receiverAccount4Address = ecKey5.getAddress(); + receiverAccount4Key = ByteArray.toHexString(ecKey5.getPrivKeyBytes()); + PublicMethed.printAddress(receiverAccount4Key); + + Long sendCoinAmount = 100000000L; + //Pre sendcoin to the test account + Assert.assertTrue(PublicMethed.sendcoin(delayAccount3Address, sendCoinAmount,fromAddress, + testKey002, blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + //Do delay send coin transaction. + logger.info("----------------No balance to send coin--------------------"); + //Test no balance to send coin. + //Query balance before send coin. + Long deplayAccountBeforeBalance = PublicMethed.queryAccount(delayAccount3Address, + blockingStubFull).getBalance(); + Long recevierAccountBeforeBalance = PublicMethed.queryAccount(receiverAccount4Address, + blockingStubFull).getBalance(); + logger.info("deplayAccountBeforeBalance " + deplayAccountBeforeBalance); + logger.info("recevierAccountBeforeBalance " + recevierAccountBeforeBalance); + Long delaySecond = 4L; + Assert.assertFalse(PublicMethed.sendcoinDelayed(receiverAccount4Address, sendCoinAmount, + delaySecond,delayAccount3Address, delayAccount3Key, blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + //Query balance after delay send coin. + Long deplayAccountAfterBalance = PublicMethed.queryAccount(delayAccount3Address, + blockingStubFull).getBalance(); + Long recevierAccountAfterDelayalance = PublicMethed.queryAccount(receiverAccount4Address, + blockingStubFull).getBalance(); + logger.info("deplayAccountAfterBalance " + deplayAccountAfterBalance); + logger.info("recevierAccountAfterDelayalance " + recevierAccountAfterDelayalance); + + Assert.assertTrue(recevierAccountAfterDelayalance == 0); + logger.info("deplayAccountBeforeBalance: " + deplayAccountBeforeBalance); + logger.info("deplayAccountAfterBalance: " + deplayAccountAfterBalance); + + Assert.assertEquals(deplayAccountBeforeBalance,deplayAccountAfterBalance); + + + logger.info("----------------No balance to create account send coin--------------------"); + //Test delay send coin to create account. + deplayAccountBeforeBalance = PublicMethed.queryAccount(delayAccount3Address, + blockingStubFull).getBalance(); + recevierAccountBeforeBalance = PublicMethed.queryAccount(receiverAccount4Address, + blockingStubFull).getBalance(); + logger.info("deplayAccountBeforeBalance " + deplayAccountBeforeBalance); + logger.info("recevierAccountBeforeBalance " + recevierAccountBeforeBalance); + Long createAccountFee = 100000L; + Assert.assertTrue(PublicMethed.sendcoinDelayed(receiverAccount4Address, + deplayAccountBeforeBalance - createAccountFee, delaySecond,delayAccount3Address, + delayAccount3Key, blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + //Query balance after delay send coin. + deplayAccountAfterBalance = PublicMethed.queryAccount(delayAccount3Address, blockingStubFull) + .getBalance(); + recevierAccountAfterDelayalance = PublicMethed.queryAccount(receiverAccount4Address, + blockingStubFull).getBalance(); + logger.info("deplayAccountAfterBalance " + deplayAccountAfterBalance); + logger.info("recevierAccountAfterDelayalance " + recevierAccountAfterDelayalance); + + Assert.assertTrue(recevierAccountAfterDelayalance == 0); + Assert.assertTrue(deplayAccountBeforeBalance - deplayAccountAfterBalance == 100000); + + + logger.info("---------------Balance enough to create account send coin--------------------"); + //Test delay send coin to create account. + createAccountFee = 100000L; + deplayAccountBeforeBalance = PublicMethed.queryAccount(delayAccount3Address, + blockingStubFull).getBalance(); + recevierAccountBeforeBalance = PublicMethed.queryAccount(receiverAccount4Address, + blockingStubFull).getBalance(); + logger.info("deplayAccountBeforeBalance " + deplayAccountBeforeBalance); + logger.info("recevierAccountBeforeBalance " + recevierAccountBeforeBalance); + Assert.assertTrue(PublicMethed.sendcoinDelayed(receiverAccount4Address, + deplayAccountBeforeBalance - createAccountFee - delayTransactionFee, + delaySecond,delayAccount3Address, delayAccount3Key, blockingStubFull)); + PublicMethed.waitProduceNextBlock(blockingStubFull); + PublicMethed.waitProduceNextBlock(blockingStubFull); + + //Query balance after delay send coin. + deplayAccountAfterBalance = PublicMethed.queryAccount(delayAccount3Address, + blockingStubFull).getBalance(); + recevierAccountAfterDelayalance = PublicMethed.queryAccount(receiverAccount4Address, + blockingStubFull).getBalance(); + logger.info("deplayAccountAfterBalance " + deplayAccountAfterBalance); + logger.info("recevierAccountAfterDelayalance " + recevierAccountAfterDelayalance); + Long receiverBalanceShouldBe = deplayAccountBeforeBalance - createAccountFee + - delayTransactionFee; + + Assert.assertEquals(recevierAccountAfterDelayalance, receiverBalanceShouldBe); + Assert.assertTrue(deplayAccountAfterBalance == 0); + } + + + + + /** + * constructor. + */ + + @AfterClass(enabled = true) + public void shutdown() throws InterruptedException { + if (channelFull != null) { + channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); + } + } +} + + diff --git a/src/test/resources/solcDir/README.txt b/src/test/resources/solcDir/README.txt new file mode 100644 index 00000000000..f390cc49698 --- /dev/null +++ b/src/test/resources/solcDir/README.txt @@ -0,0 +1 @@ +to storage solidity compiler \ No newline at end of file diff --git a/src/test/resources/solidityFile.xml b/src/test/resources/solidityFile.xml new file mode 100644 index 00000000000..6082ba41ccd --- /dev/null +++ b/src/test/resources/solidityFile.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/soliditycode/addMsg001Nonpayable.sol b/src/test/resources/soliditycode/addMsg001Nonpayable.sol new file mode 100644 index 00000000000..d1294f2336a --- /dev/null +++ b/src/test/resources/soliditycode/addMsg001Nonpayable.sol @@ -0,0 +1,20 @@ +//pragma solidity ^0.4.24; + +contract IllegalDecorate { + +event log(uint256); +constructor() payable public{} + +function() payable external{} + +function transferTokenWithOutPayable(address payable toAddress, uint256 tokenValue)public { +// function transferTokenWithValue(address toAddress, uint256 tokenValue) payable public { +emit log(msg.value); +emit log(msg.tokenvalue); +emit log(msg.tokenid); +toAddress.transferToken(msg.tokenvalue, msg.tokenid); +toAddress.transfer(msg.value); + +} + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/addMsg002View.sol b/src/test/resources/soliditycode/addMsg002View.sol new file mode 100644 index 00000000000..423bb68e3ed --- /dev/null +++ b/src/test/resources/soliditycode/addMsg002View.sol @@ -0,0 +1,20 @@ +//pragma solidity ^0.4.24; + +contract IllegalDecorate { + +constructor() payable public{} + +function() payable external{} + +event log(uint256); + +function transferTokenWithView(address payable toAddress, uint256 tokenValue) public view{ +emit log(msg.value); +emit log(msg.tokenvalue); +emit log(msg.tokenid); +toAddress.transferToken(msg.tokenvalue, msg.tokenid); +toAddress.transfer(msg.value); +} + +} + diff --git a/src/test/resources/soliditycode/addMsg003Constant.sol b/src/test/resources/soliditycode/addMsg003Constant.sol new file mode 100644 index 00000000000..0f0ab7553e0 --- /dev/null +++ b/src/test/resources/soliditycode/addMsg003Constant.sol @@ -0,0 +1,19 @@ +//pragma solidity ^0.4.24; + +contract IllegalDecorate { + +constructor() payable public{} + +function() payable external{} + +event log(uint256); + +function transferTokenWithConstant(address payable toAddress, uint256 tokenValue) public constant{ +emit log(msg.value); +emit log(msg.tokenvalue); +emit log(msg.tokenid); +toAddress.transferToken(msg.tokenvalue, msg.tokenid); +toAddress.transfer(msg.value); +} + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/addMsg004Pure.sol b/src/test/resources/soliditycode/addMsg004Pure.sol new file mode 100644 index 00000000000..b5d3a4e4aee --- /dev/null +++ b/src/test/resources/soliditycode/addMsg004Pure.sol @@ -0,0 +1,19 @@ +//pragma solidity ^0.4.24; + +contract IllegalDecorate { + +constructor() payable public{} + +function() payable external{} + +event log(uint256); + +function transferTokenWithPure(address payable toAddress, uint256 tokenValue) public pure{ +emit log(msg.value); +emit log(msg.tokenvalue); +emit log(msg.tokenid); +toAddress.transferToken(msg.tokenvalue, msg.tokenid); +toAddress.transfer(msg.value); +} + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/addTransferToken001Nonpayable.sol b/src/test/resources/soliditycode/addTransferToken001Nonpayable.sol new file mode 100644 index 00000000000..c8d0dcc7560 --- /dev/null +++ b/src/test/resources/soliditycode/addTransferToken001Nonpayable.sol @@ -0,0 +1,13 @@ +//pragma solidity ^0.4.24; + + contract IllegalDecorate { + + constructor() payable public{} + + function() payable external{} + + function transferTokenWithOutPayable(address payable toAddress,trcToken id, uint256 tokenValue)public { + + toAddress.transferToken(tokenValue, id); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/addTransferToken001payable.sol b/src/test/resources/soliditycode/addTransferToken001payable.sol new file mode 100644 index 00000000000..803d66ad75e --- /dev/null +++ b/src/test/resources/soliditycode/addTransferToken001payable.sol @@ -0,0 +1,13 @@ +//pragma solidity ^0.4.24; + + contract IllegalDecorate { + + constructor() payable public{} + + function() payable external{} + + function transferTokenWithOutPayable(address payable toAddress,trcToken id, uint256 tokenValue) public payable{ + + toAddress.transferToken(tokenValue, id); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/addTransferToken002View.sol b/src/test/resources/soliditycode/addTransferToken002View.sol new file mode 100644 index 00000000000..109f46386ce --- /dev/null +++ b/src/test/resources/soliditycode/addTransferToken002View.sol @@ -0,0 +1,15 @@ +//pragma solidity ^0.4.24; + +contract IllegalDecorate { + + constructor() payable public{} + + function() payable external{} + + function transferTokenWithView(address payable toAddress,trcToken id, uint256 tokenValue) public view{ + + toAddress.transferToken(tokenValue, id); + + } + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/addTransferToken003Constant.sol b/src/test/resources/soliditycode/addTransferToken003Constant.sol new file mode 100644 index 00000000000..fb1a2cbbbb4 --- /dev/null +++ b/src/test/resources/soliditycode/addTransferToken003Constant.sol @@ -0,0 +1,15 @@ +//pragma solidity ^0.4.24; + +contract IllegalDecorate { + + constructor() payable public{} + + function() payable external{} + + function transferTokenWithConstant(address payable toAddress, uint256 tokenValue) public constant{ + + toAddress.transferToken(tokenValue, 0x6e6d62); + + } + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/addTransferToken004Pure.sol b/src/test/resources/soliditycode/addTransferToken004Pure.sol new file mode 100644 index 00000000000..7ea2bf0a40b --- /dev/null +++ b/src/test/resources/soliditycode/addTransferToken004Pure.sol @@ -0,0 +1,15 @@ +//pragma solidity ^0.4.24; + +contract IllegalDecorate { + + constructor() payable public{} + + function() payable external{} + + function transferTokenWithPure(address payable toAddress, uint256 tokenValue) public pure{ + + toAddress.transferToken(tokenValue, 0x6e6d62); + + } + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/addTrcToken001Assemble.sol b/src/test/resources/soliditycode/addTrcToken001Assemble.sol new file mode 100644 index 00000000000..a93d9046a3f --- /dev/null +++ b/src/test/resources/soliditycode/addTrcToken001Assemble.sol @@ -0,0 +1,62 @@ +//pragma solidity ^0.4.24; + +contract InAssemble { + +mapping(trcToken => uint256) tokenCnt; +mapping(uint256 => mapping(trcToken => trcToken)) cntTokenToken; +constructor () payable public {} +function getBalance (address addr) view public returns(uint256 r) { +assembly{ +r := balance(addr) +} +} + +function getTokenBalanceConstant (address addr, trcToken tokenId) view public returns(uint256 r) { +assembly{ +r := tokenbalance(tokenId, addr) +} +} + +function getTokenBalance (address addr, trcToken tokenId) public returns(uint256 r) { +assembly{ +r := tokenbalance(tokenId, addr) +} +} + +function transferTokenInAssembly(address addr, trcToken tokenId, uint256 tokenValue) public payable { +bytes4 sig = bytes4(keccak256("()")); // function signature + +assembly { +let x := mload(0x40) // get empty storage location +mstore(x,sig) // 4 bytes - place signature in empty storage + +let ret := calltoken(gas, addr, tokenValue, tokenId, +x, // input +0x04, // input size = 4 bytes +x, // output stored at input location, save space +0x0 // output size = 0 bytes +) + +// let ret := calltoken(gas, addr, tokenValue, +// x, // input +// 0x04, // input size = 4 bytes +// x, // output stored at input location, save space +// 0x0 // output size = 0 bytes +// ) // ERROR + + +mstore(0x40, add(x,0x20)) // update free memory pointer +} + +} + +function trcTokenInMap(trcToken tokenId, uint256 tokenValue) public returns(uint256 r) { +tokenCnt[tokenId] += tokenValue; +r = tokenCnt[tokenId]; +} + +function cntTokenTokenInMap(trcToken tokenId1, trcToken tokenId2, uint256 tokenValue) public returns(trcToken r) { +cntTokenToken[tokenValue][tokenId1] = tokenId2; +r = cntTokenToken[tokenValue][tokenId1]; +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/addTrcToken002Cat.sol b/src/test/resources/soliditycode/addTrcToken002Cat.sol new file mode 100644 index 00000000000..6d9c169330d --- /dev/null +++ b/src/test/resources/soliditycode/addTrcToken002Cat.sol @@ -0,0 +1,2051 @@ +//pragma solidity ^0.4.11; + + +/** + * @title Ownable + * @dev The Ownable contract has an owner address, and provides basic authorization control + * functions, this simplifies the implementation of "user permissions". + */ +contract Ownable { + address public owner; + + + /** + * @dev The Ownable constructor sets the original `owner` of the contract to the sender + * account. + */ + constructor() public { + owner = msg.sender; + } + + + /** + * @dev Throws if called by any account other than the owner. + */ + modifier onlyOwner() { + require(msg.sender == owner); + _; + } + + + /** + * @dev Allows the current owner to transfer control of the contract to a newOwner. + * @param newOwner The address to transfer ownership to. + */ + function transferOwnership(address newOwner) public onlyOwner { + if (newOwner != address(0)) { + owner = newOwner; + } + } + +} + + + + +/// @title A facet of KittyCore that manages special access privileges. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. +contract KittyAccessControl { + // This facet controls access control for CryptoKitties. There are four roles managed here: + // + // - The CEO: The CEO can reassign other roles and change the addresses of our dependent smart + // contracts. It is also the only role that can unpause the smart contract. It is initially + // set to the address that created the smart contract in the KittyCore constructor. + // + // - The CFO: The CFO can withdraw funds from KittyCore and its auction contracts. + // + // - The COO: The COO can release gen0 kitties to auction, and mint promo cats. + // + // It should be noted that these roles are distinct without overlap in their access abilities, the + // abilities listed for each role above are exhaustive. In particular, while the CEO can assign any + // address to any role, the CEO address itself doesn't have the ability to act in those roles. This + // restriction is intentional so that we aren't tempted to use the CEO address frequently out of + // convenience. The less we use an address, the less likely it is that we somehow compromise the + // account. + + /// @dev Emited when contract is upgraded - See README.md for updgrade plan + event ContractUpgrade(address newContract); + + // The addresses of the accounts (or contracts) that can execute actions within each roles. + address public ceoAddress; + address payable public cfoAddress; + address public cooAddress; + + // @dev Keeps track whether the contract is paused. When that is true, most actions are blocked + bool public paused = false; + + /// @dev Access modifier for CEO-only functionality + modifier onlyCEO() { + require(msg.sender == ceoAddress); + _; + } + + /// @dev Access modifier for CFO-only functionality + modifier onlyCFO() { + require(msg.sender == cfoAddress); + _; + } + + /// @dev Access modifier for COO-only functionality + modifier onlyCOO() { + require(msg.sender == cooAddress); + _; + } + + modifier onlyCLevel() { + require( + msg.sender == cooAddress || + msg.sender == ceoAddress || + msg.sender == cfoAddress + ); + _; + } + + /// @dev Assigns a new address to act as the CEO. Only available to the current CEO. + /// @param _newCEO The address of the new CEO + function setCEO(address _newCEO) external onlyCEO { + require(_newCEO != address(0)); + + ceoAddress = _newCEO; + } + + /// @dev Assigns a new address to act as the CFO. Only available to the current CEO. + /// @param _newCFO The address of the new CFO + function setCFO(address payable _newCFO) external onlyCEO { + require(_newCFO != address(0)); + + cfoAddress = _newCFO; + } + + /// @dev Assigns a new address to act as the COO. Only available to the current CEO. + /// @param _newCOO The address of the new COO + function setCOO(address _newCOO) external onlyCEO { + require(_newCOO != address(0)); + + cooAddress = _newCOO; + } + + /*** Pausable functionality adapted from OpenZeppelin ***/ + + /// @dev Modifier to allow actions only when the contract IS NOT paused + modifier whenNotPaused() { + require(!paused); + _; + } + + /// @dev Modifier to allow actions only when the contract IS paused + modifier whenPaused { + require(paused); + _; + } + + /// @dev Called by any "C-level" role to pause the contract. Used only when + /// a bug or exploit is detected and we need to limit damage. + function pause() external onlyCLevel whenNotPaused { + paused = true; + } + + /// @dev Unpauses the smart contract. Can only be called by the CEO, since + /// one reason we may pause the contract is when CFO or COO accounts are + /// compromised. + /// @notice This is public rather than external so it can be called by + /// derived contracts. + function unpause() public onlyCEO whenPaused { + // can't unpause if contract was upgraded + paused = false; + } +} + + + + +/// @title Base contract for CryptoKitties. Holds all common structs, events and base variables. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. +contract KittyBase is KittyAccessControl { + /*** EVENTS ***/ + + /// @dev The Birth event is fired whenever a new kitten comes into existence. This obviously + /// includes any time a cat is created through the giveBirth method, but it is also called + /// when a new gen0 cat is created. + event Birth(address owner, uint256 kittyId, uint256 matronId, uint256 sireId, uint256 genes); + + /// @dev Transfer event as defined in current draft of ERC721. Emitted every time a kitten + /// ownership is assigned, including births. + event Transfer(address from, address to, uint256 tokenId); + + /*** DATA TYPES ***/ + + /// @dev The main Kitty struct. Every cat in CryptoKitties is represented by a copy + /// of this structure, so great care was taken to ensure that it fits neatly into + /// exactly two 256-bit words. Note that the order of the members in this structure + /// is important because of the byte-packing rules used by Ethereum. + /// Ref: http://solidity.readthedocs.io/en/develop/miscellaneous.html + struct Kitty { + // The Kitty's genetic code is packed into these 256-bits, the format is + // sooper-sekret! A cat's genes never change. + uint256 genes; + + // The timestamp from the block when this cat came into existence. + uint64 birthTime; + + // The minimum timestamp after which this cat can engage in breeding + // activities again. This same timestamp is used for the pregnancy + // timer (for matrons) as well as the siring cooldown. + uint64 cooldownEndBlock; + + // The ID of the parents of this kitty, set to 0 for gen0 cats. + // Note that using 32-bit unsigned integers limits us to a "mere" + // 4 billion cats. This number might seem small until you realize + // that Ethereum currently has a limit of about 500 million + // transactions per year! So, this definitely won't be a problem + // for several years (even as Ethereum learns to scale). + uint32 matronId; + uint32 sireId; + + // Set to the ID of the sire cat for matrons that are pregnant, + // zero otherwise. A non-zero value here is how we know a cat + // is pregnant. Used to retrieve the genetic material for the new + // kitten when the birth transpires. + uint32 siringWithId; + + // Set to the index in the cooldown array (see below) that represents + // the current cooldown duration for this Kitty. This starts at zero + // for gen0 cats, and is initialized to floor(generation/2) for others. + // Incremented by one for each successful breeding action, regardless + // of whether this cat is acting as matron or sire. + uint16 cooldownIndex; + + // The "generation number" of this cat. Cats minted by the CK contract + // for sale are called "gen0" and have a generation number of 0. The + // generation number of all other cats is the larger of the two generation + // numbers of their parents, plus one. + // (i.e. max(matron.generation, sire.generation) + 1) + uint16 generation; + } + + /*** CONSTANTS ***/ + + /// @dev A lookup table indicating the cooldown duration after any successful + /// breeding action, called "pregnancy time" for matrons and "siring cooldown" + /// for sires. Designed such that the cooldown roughly doubles each time a cat + /// is bred, encouraging owners not to just keep breeding the same cat over + /// and over again. Caps out at one week (a cat can breed an unbounded number + /// of times, and the maximum cooldown is always seven days). + uint32[14] public cooldowns = [ + uint32(1 minutes), + uint32(2 minutes), + uint32(5 minutes), + uint32(10 minutes), + uint32(30 minutes), + uint32(1 hours), + uint32(2 hours), + uint32(4 hours), + uint32(8 hours), + uint32(16 hours), + uint32(1 days), + uint32(2 days), + uint32(4 days), + uint32(7 days) + ]; + + // An approximation of currently how many seconds are in between blocks. + uint256 public secondsPerBlock = 15; + + /*** STORAGE ***/ + + /// @dev An array containing the Kitty struct for all Kitties in existence. The ID + /// of each cat is actually an index into this array. Note that ID 0 is a negacat, + /// the unKitty, the mythical beast that is the parent of all gen0 cats. A bizarre + /// creature that is both matron and sire... to itself! Has an invalid genetic code. + /// In other words, cat ID 0 is invalid... ;-) + Kitty[] kitties; + + /// @dev A mapping from cat IDs to the address that owns them. All cats have + /// some valid owner address, even gen0 cats are created with a non-zero owner. + mapping (uint256 => address) public kittyIndexToOwner; + + // @dev A mapping from owner address to count of tokens that address owns. + // Used internally inside balanceOf() to resolve ownership count. + mapping (address => uint256) ownershipTokenCount; + + /// @dev A mapping from KittyIDs to an address that has been approved to call + /// transferFrom(). Each Kitty can only have one approved address for transfer + /// at any time. A zero value means no approval is outstanding. + mapping (uint256 => address) public kittyIndexToApproved; + + /// @dev A mapping from KittyIDs to an address that has been approved to use + /// this Kitty for siring via breedWith(). Each Kitty can only have one approved + /// address for siring at any time. A zero value means no approval is outstanding. + mapping (uint256 => address) public sireAllowedToAddress; + + /// @dev The address of the ClockAuction contract that handles sales of Kitties. This + /// same contract handles both peer-to-peer sales as well as the gen0 sales which are + /// initiated every 15 minutes. + SaleClockAuction public saleAuction; + + /// @dev The address of a custom ClockAuction subclassed contract that handles siring + /// auctions. Needs to be separate from saleAuction because the actions taken on success + /// after a sales and siring auction are quite different. + SiringClockAuction public siringAuction; + + /// @dev Assigns ownership of a specific Kitty to an address. + function _transfer(address _from, address _to, uint256 _tokenId) internal { + // Since the number of kittens is capped to 2^32 we can't overflow this + ownershipTokenCount[_to]++; + // transfer ownership + kittyIndexToOwner[_tokenId] = _to; + // When creating new kittens _from is 0x0, but we can't account that address. + if (_from != address(0)) { + ownershipTokenCount[_from]--; + // once the kitten is transferred also clear sire allowances + delete sireAllowedToAddress[_tokenId]; + // clear any previously approved ownership exchange + delete kittyIndexToApproved[_tokenId]; + } + // Emit the transfer event. + emit Transfer(_from, _to, _tokenId); + } + + /// @dev An internal method that creates a new kitty and stores it. This + /// method doesn't do any checking and should only be called when the + /// input data is known to be valid. Will generate both a Birth event + /// and a Transfer event. + /// @param _matronId The kitty ID of the matron of this cat (zero for gen0) + /// @param _sireId The kitty ID of the sire of this cat (zero for gen0) + /// @param _generation The generation number of this cat, must be computed by caller. + /// @param _genes The kitty's genetic code. + /// @param _owner The inital owner of this cat, must be non-zero (except for the unKitty, ID 0) + function _createKitty( + uint256 _matronId, + uint256 _sireId, + uint256 _generation, + uint256 _genes, + address _owner + ) + internal + returns (uint) + { + // These requires are not strictly necessary, our calling code should make + // sure that these conditions are never broken. However! _createKitty() is already + // an expensive call (for storage), and it doesn't hurt to be especially careful + // to ensure our data structures are always valid. + require(_matronId == uint256(uint32(_matronId))); + require(_sireId == uint256(uint32(_sireId))); + require(_generation == uint256(uint16(_generation))); + + // New kitty starts with the same cooldown as parent gen/2 + uint16 cooldownIndex = uint16(_generation / 2); + if (cooldownIndex > 13) { + cooldownIndex = 13; + } + + Kitty memory _kitty = Kitty({ + genes: _genes, + birthTime: uint64(now), + cooldownEndBlock: 0, + matronId: uint32(_matronId), + sireId: uint32(_sireId), + siringWithId: 0, + cooldownIndex: cooldownIndex, + generation: uint16(_generation) + }); + uint256 newKittenId = kitties.push(_kitty) - 1; + + // It's probably never going to happen, 4 billion cats is A LOT, but + // let's just be 100% sure we never let this happen. + require(newKittenId == uint256(uint32(newKittenId))); + + // emit the birth event + emit Birth( + _owner, + newKittenId, + uint256(_kitty.matronId), + uint256(_kitty.sireId), + _kitty.genes + ); + + // This will assign ownership, and also emit the Transfer event as + // per ERC721 draft + _transfer(address(0), _owner, newKittenId); + + return newKittenId; + } + + // Any C-level can fix how many seconds per blocks are currently observed. + function setSecondsPerBlock(uint256 secs) external onlyCLevel { + require(secs < cooldowns[0]); + secondsPerBlock = secs; + } +} + + +/// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens +/// @author Dieter Shirley (https://github.com/dete) +contract ERC721 { + // Required methods + function totalSupply() public view returns (uint256 total); + function balanceOf(address _owner) public view returns (uint256 balance); + function ownerOf(uint256 _tokenId) external view returns (address owner); + function approve(address _to, uint256 _tokenId) external; + function transfer(address _to, uint256 _tokenId) external; + function transferFrom(address _from, address _to, uint256 _tokenId) external; + + // Events + event Transfer(address from, address to, uint256 tokenId); + event Approval(address owner, address approved, uint256 tokenId); + + // Optional + // function name() public view returns (string name); + // function symbol() public view returns (string symbol); + // function tokensOfOwner(address _owner) external view returns (uint256[] tokenIds); + // function tokenMetadata(uint256 _tokenId, string _preferredTransport) public view returns (string infoUrl); + + // ERC-165 Compatibility (https://github.com/ethereum/EIPs/issues/165) + function supportsInterface(bytes4 _interfaceID) external view returns (bool); +} + + +/// @title The facet of the CryptoKitties core contract that manages ownership, ERC-721 (draft) compliant. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev Ref: https://github.com/ethereum/EIPs/issues/721 +/// See the KittyCore contract documentation to understand how the various contract facets are arranged. +contract KittyOwnership is ERC721, KittyBase { + + /// @notice Name and symbol of the non fungible token, as defined in ERC721. + string public constant name = "CryptoKitties"; + string public constant symbol = "CK"; + + // The contract that will return kitty metadata + ERC721Metadata public erc721Metadata; + + bytes4 constant InterfaceSignature_ERC165 = + bytes4(keccak256('supportsInterface(bytes4)')); + + bytes4 constant InterfaceSignature_ERC721 = + bytes4(keccak256('name()')) ^ + bytes4(keccak256('symbol()')) ^ + bytes4(keccak256('totalSupply()')) ^ + bytes4(keccak256('balanceOf(address)')) ^ + bytes4(keccak256('ownerOf(uint256)')) ^ + bytes4(keccak256('approve(address,uint256)')) ^ + bytes4(keccak256('transfer(address,uint256)')) ^ + bytes4(keccak256('transferFrom(address,address,uint256)')) ^ + bytes4(keccak256('tokensOfOwner(address)')) ^ + bytes4(keccak256('tokenMetadata(uint256,string)')); + + /// @notice Introspection interface as per ERC-165 (https://github.com/ethereum/EIPs/issues/165). + /// Returns true for any standardized interfaces implemented by this contract. We implement + /// ERC-165 (obviously!) and ERC-721. + function supportsInterface(bytes4 _interfaceID) external view returns (bool) + { + // DEBUG ONLY + //require((InterfaceSignature_ERC165 == 0x01ffc9a7) && (InterfaceSignature_ERC721 == 0x9a20483d)); + + return ((_interfaceID == InterfaceSignature_ERC165) || (_interfaceID == InterfaceSignature_ERC721)); + } + + /// @dev Set the address of the sibling contract that tracks metadata. + /// CEO only. + function setMetadataAddress(address _contractAddress) public onlyCEO { + erc721Metadata = ERC721Metadata(_contractAddress); + } + + // Internal utility functions: These functions all assume that their input arguments + // are valid. We leave it to public methods to sanitize their inputs and follow + // the required logic. + + /// @dev Checks if a given address is the current owner of a particular Kitty. + /// @param _claimant the address we are validating against. + /// @param _tokenId kitten id, only valid when > 0 + function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { + return kittyIndexToOwner[_tokenId] == _claimant; + } + + /// @dev Checks if a given address currently has transferApproval for a particular Kitty. + /// @param _claimant the address we are confirming kitten is approved for. + /// @param _tokenId kitten id, only valid when > 0 + function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) { + return kittyIndexToApproved[_tokenId] == _claimant; + } + + /// @dev Marks an address as being approved for transferFrom(), overwriting any previous + /// approval. Setting _approved to address(0) clears all transfer approval. + /// NOTE: _approve() does NOT send the Approval event. This is intentional because + /// _approve() and transferFrom() are used together for putting Kitties on auction, and + /// there is no value in spamming the log with Approval events in that case. + function _approve(uint256 _tokenId, address _approved) internal { + kittyIndexToApproved[_tokenId] = _approved; + } + + /// @notice Returns the number of Kitties owned by a specific address. + /// @param _owner The owner address to check. + /// @dev Required for ERC-721 compliance + function balanceOf(address _owner) public view returns (uint256 count) { + return ownershipTokenCount[_owner]; + } + + /// @notice Transfers a Kitty to another address. If transferring to a smart + /// contract be VERY CAREFUL to ensure that it is aware of ERC-721 (or + /// CryptoKitties specifically) or your Kitty may be lost forever. Seriously. + /// @param _to The address of the recipient, can be a user or contract. + /// @param _tokenId The ID of the Kitty to transfer. + /// @dev Required for ERC-721 compliance. + function transfer( + address _to, + uint256 _tokenId + ) + external + whenNotPaused + { + // Safety check to prevent against an unexpected 0x0 default. + require(_to != address(0)); + // Disallow transfers to this contract to prevent accidental misuse. + // The contract should never own any kitties (except very briefly + // after a gen0 cat is created and before it goes on auction). + require(_to != address(this)); + // Disallow transfers to the auction contracts to prevent accidental + // misuse. Auction contracts should only take ownership of kitties + // through the allow + transferFrom flow. + require(_to != address(saleAuction)); + require(_to != address(siringAuction)); + + // You can only send your own cat. + require(_owns(msg.sender, _tokenId)); + + // Reassign ownership, clear pending approvals, emit Transfer event. + _transfer(msg.sender, _to, _tokenId); + } + + /// @notice Grant another address the right to transfer a specific Kitty via + /// transferFrom(). This is the preferred flow for transfering NFTs to contracts. + /// @param _to The address to be granted transfer approval. Pass address(0) to + /// clear all approvals. + /// @param _tokenId The ID of the Kitty that can be transferred if this call succeeds. + /// @dev Required for ERC-721 compliance. + function approve( + address _to, + uint256 _tokenId + ) + external + whenNotPaused + { + // Only an owner can grant transfer approval. + require(_owns(msg.sender, _tokenId)); + + // Register the approval (replacing any previous approval). + _approve(_tokenId, _to); + + // Emit approval event. + emit Approval(msg.sender, _to, _tokenId); + } + + /// @notice Transfer a Kitty owned by another address, for which the calling address + /// has previously been granted transfer approval by the owner. + /// @param _from The address that owns the Kitty to be transfered. + /// @param _to The address that should take ownership of the Kitty. Can be any address, + /// including the caller. + /// @param _tokenId The ID of the Kitty to be transferred. + /// @dev Required for ERC-721 compliance. + function transferFrom( + address _from, + address _to, + uint256 _tokenId + ) + external + whenNotPaused + { + // Safety check to prevent against an unexpected 0x0 default. + require(_to != address(0)); + // Disallow transfers to this contract to prevent accidental misuse. + // The contract should never own any kitties (except very briefly + // after a gen0 cat is created and before it goes on auction). + require(_to != address(this)); + // Check for approval and valid ownership + require(_approvedFor(msg.sender, _tokenId)); + require(_owns(_from, _tokenId)); + + // Reassign ownership (also clears pending approvals and emits Transfer event). + _transfer(_from, _to, _tokenId); + } + + /// @notice Returns the total number of Kitties currently in existence. + /// @dev Required for ERC-721 compliance. + function totalSupply() public view returns (uint) { + return kitties.length - 1; + } + + /// @notice Returns the address currently assigned ownership of a given Kitty. + /// @dev Required for ERC-721 compliance. + function ownerOf(uint256 _tokenId) + external + view + returns (address owner) + { + owner = kittyIndexToOwner[_tokenId]; + + require(owner != address(0)); + } + + /// @notice Returns a list of all Kitty IDs assigned to an address. + /// @param _owner The owner whose Kitties we are interested in. + /// @dev This method MUST NEVER be called by smart contract code. First, it's fairly + /// expensive (it walks the entire Kitty array looking for cats belonging to owner), + /// but it also returns a dynamic array, which is only supported for web3 calls, and + /// not contract-to-contract calls. + function tokensOfOwner(address _owner) external view returns(uint256[] memory ownerTokens) { + uint256 tokenCount = balanceOf(_owner); + + if (tokenCount == 0) { + // Return an empty array + return new uint256[](0); + } else { + uint256[] memory result = new uint256[](tokenCount); + uint256 totalCats = totalSupply(); + uint256 resultIndex = 0; + + // We count on the fact that all cats have IDs starting at 1 and increasing + // sequentially up to the totalCat count. + uint256 catId; + + for (catId = 1; catId <= totalCats; catId++) { + if (kittyIndexToOwner[catId] == _owner) { + result[resultIndex] = catId; + resultIndex++; + } + } + + return result; + } + } + + /// @dev Adapted from memcpy() by @arachnid (Nick Johnson ) + /// This method is licenced under the Apache License. + /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol + function _memcpy(uint _dest, uint _src, uint _len) private view { + // Copy word-length chunks while possible + for(; _len >= 32; _len -= 32) { + assembly { + mstore(_dest, mload(_src)) + } + _dest += 32; + _src += 32; + } + + // Copy remaining bytes + uint256 mask = 256 ** (32 - _len) - 1; + assembly { + let srcpart := and(mload(_src), not(mask)) + let destpart := and(mload(_dest), mask) + mstore(_dest, or(destpart, srcpart)) + } + } + + /// @dev Adapted from toString(slice) by @arachnid (Nick Johnson ) + /// This method is licenced under the Apache License. + /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol + function _toString(bytes32[4] memory _rawBytes, uint256 _stringLength) private view returns (string memory) { + string memory outputString = new string(_stringLength); + uint256 outputPtr; + uint256 bytesPtr; + + assembly { + outputPtr := add(outputString, 32) + bytesPtr := _rawBytes + } + + _memcpy(outputPtr, bytesPtr, _stringLength); + + return outputString; + } + + /// @notice Returns a URI pointing to a metadata package for this token conforming to + /// ERC-721 (https://github.com/ethereum/EIPs/issues/721) + /// @param _tokenId The ID number of the Kitty whose metadata should be returned. + function tokenMetadata(uint256 _tokenId, string calldata _preferredTransport) external view returns (string memory infoUrl) { + require( address(erc721Metadata) != address(0)); + bytes32[4] memory buffer; + uint256 count; + (buffer, count) = erc721Metadata.getMetadata(_tokenId, _preferredTransport); + + return _toString(buffer, count); + } +} + + + + +/// @title A facet of KittyCore that manages Kitty siring, gestation, and birth. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. +contract KittyBreeding is KittyOwnership { + + /// @dev The Pregnant event is fired when two cats successfully breed and the pregnancy + /// timer begins for the matron. + event Pregnant(address owner, uint256 matronId, uint256 sireId, uint256 cooldownEndBlock); + + /// @notice The minimum payment required to use breedWithAuto(). This fee goes towards + /// the gas cost paid by whatever calls giveBirth(), and can be dynamically updated by + /// the COO role as the gas price changes. + uint256 public autoBirthFee = 2 sun; + + // Keeps track of number of pregnant kitties. + uint256 public pregnantKitties; + + /// @dev The address of the sibling contract that is used to implement the sooper-sekret + /// genetic combination algorithm. + GeneScienceInterface public geneScience; + + /// @dev Update the address of the genetic contract, can only be called by the CEO. + /// @param _address An address of a GeneScience contract instance to be used from this point forward. + function setGeneScienceAddress(address _address) external onlyCEO { + GeneScienceInterface candidateContract = GeneScienceInterface(_address); + + // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 + require(candidateContract.isGeneScience()); + + // Set the new contract address + geneScience = candidateContract; + } + + /// @dev Checks that a given kitten is able to breed. Requires that the + /// current cooldown is finished (for sires) and also checks that there is + /// no pending pregnancy. + function _isReadyToBreed(Kitty memory _kit) internal view returns (bool) { + // In addition to checking the cooldownEndBlock, we also need to check to see if + // the cat has a pending birth; there can be some period of time between the end + // of the pregnacy timer and the birth event. + return (_kit.siringWithId == 0) && (_kit.cooldownEndBlock <= uint64(block.number)); + } + + /// @dev Check if a sire has authorized breeding with this matron. True if both sire + /// and matron have the same owner, or if the sire has given siring permission to + /// the matron's owner (via approveSiring()). + function _isSiringPermitted(uint256 _sireId, uint256 _matronId) internal view returns (bool) { + address matronOwner = kittyIndexToOwner[_matronId]; + address sireOwner = kittyIndexToOwner[_sireId]; + + // Siring is okay if they have same owner, or if the matron's owner was given + // permission to breed with this sire. + return (matronOwner == sireOwner || sireAllowedToAddress[_sireId] == matronOwner); + } + + /// @dev Set the cooldownEndTime for the given Kitty, based on its current cooldownIndex. + /// Also increments the cooldownIndex (unless it has hit the cap). + /// @param _kitten A reference to the Kitty in storage which needs its timer started. + function _triggerCooldown(Kitty storage _kitten) internal { + // Compute an estimation of the cooldown time in blocks (based on current cooldownIndex). + _kitten.cooldownEndBlock = uint64((cooldowns[_kitten.cooldownIndex]/secondsPerBlock) + block.number); + + // Increment the breeding count, clamping it at 13, which is the length of the + // cooldowns array. We could check the array size dynamically, but hard-coding + // this as a constant saves gas. Yay, Solidity! + if (_kitten.cooldownIndex < 13) { + _kitten.cooldownIndex += 1; + } + } + + /// @notice Grants approval to another user to sire with one of your Kitties. + /// @param _addr The address that will be able to sire with your Kitty. Set to + /// address(0) to clear all siring approvals for this Kitty. + /// @param _sireId A Kitty that you own that _addr will now be able to sire with. + function approveSiring(address _addr, uint256 _sireId) + external + whenNotPaused + { + require(_owns(msg.sender, _sireId)); + sireAllowedToAddress[_sireId] = _addr; + } + + /// @dev Updates the minimum payment required for calling giveBirthAuto(). Can only + /// be called by the COO address. (This fee is used to offset the gas cost incurred + /// by the autobirth daemon). + function setAutoBirthFee(uint256 val) external onlyCOO { + autoBirthFee = val; + } + + /// @dev Checks to see if a given Kitty is pregnant and (if so) if the gestation + /// period has passed. + function _isReadyToGiveBirth(Kitty memory _matron) private view returns (bool) { + return (_matron.siringWithId != 0) && (_matron.cooldownEndBlock <= uint64(block.number)); + } + + /// @notice Checks that a given kitten is able to breed (i.e. it is not pregnant or + /// in the middle of a siring cooldown). + /// @param _kittyId reference the id of the kitten, any user can inquire about it + function isReadyToBreed(uint256 _kittyId) + public + view + returns (bool) + { + require(_kittyId > 0); + Kitty storage kit = kitties[_kittyId]; + return _isReadyToBreed(kit); + } + + /// @dev Checks whether a kitty is currently pregnant. + /// @param _kittyId reference the id of the kitten, any user can inquire about it + function isPregnant(uint256 _kittyId) + public + view + returns (bool) + { + require(_kittyId > 0); + // A kitty is pregnant if and only if this field is set + return kitties[_kittyId].siringWithId != 0; + } + + /// @dev Internal check to see if a given sire and matron are a valid mating pair. DOES NOT + /// check ownership permissions (that is up to the caller). + /// @param _matron A reference to the Kitty struct of the potential matron. + /// @param _matronId The matron's ID. + /// @param _sire A reference to the Kitty struct of the potential sire. + /// @param _sireId The sire's ID + function _isValidMatingPair( + Kitty storage _matron, + uint256 _matronId, + Kitty storage _sire, + uint256 _sireId + ) + private + view + returns(bool) + { + // A Kitty can't breed with itself! + if (_matronId == _sireId) { + return false; + } + + // Kitties can't breed with their parents. + if (_matron.matronId == _sireId || _matron.sireId == _sireId) { + return false; + } + if (_sire.matronId == _matronId || _sire.sireId == _matronId) { + return false; + } + + // We can short circuit the sibling check (below) if either cat is + // gen zero (has a matron ID of zero). + if (_sire.matronId == 0 || _matron.matronId == 0) { + return true; + } + + // Kitties can't breed with full or half siblings. + if (_sire.matronId == _matron.matronId || _sire.matronId == _matron.sireId) { + return false; + } + if (_sire.sireId == _matron.matronId || _sire.sireId == _matron.sireId) { + return false; + } + + // Everything seems cool! Let's get DTF. + return true; + } + + /// @dev Internal check to see if a given sire and matron are a valid mating pair for + /// breeding via auction (i.e. skips ownership and siring approval checks). + function _canBreedWithViaAuction(uint256 _matronId, uint256 _sireId) + internal + view + returns (bool) + { + Kitty storage matron = kitties[_matronId]; + Kitty storage sire = kitties[_sireId]; + return _isValidMatingPair(matron, _matronId, sire, _sireId); + } + + /// @notice Checks to see if two cats can breed together, including checks for + /// ownership and siring approvals. Does NOT check that both cats are ready for + /// breeding (i.e. breedWith could still fail until the cooldowns are finished). + /// TODO: Shouldn't this check pregnancy and cooldowns?!? + /// @param _matronId The ID of the proposed matron. + /// @param _sireId The ID of the proposed sire. + function canBreedWith(uint256 _matronId, uint256 _sireId) + external + view + returns(bool) + { + require(_matronId > 0); + require(_sireId > 0); + Kitty storage matron = kitties[_matronId]; + Kitty storage sire = kitties[_sireId]; + return _isValidMatingPair(matron, _matronId, sire, _sireId) && + _isSiringPermitted(_sireId, _matronId); + } + + /// @dev Internal utility function to initiate breeding, assumes that all breeding + /// requirements have been checked. + function _breedWith(uint256 _matronId, uint256 _sireId) internal { + // Grab a reference to the Kitties from storage. + Kitty storage sire = kitties[_sireId]; + Kitty storage matron = kitties[_matronId]; + + // Mark the matron as pregnant, keeping track of who the sire is. + matron.siringWithId = uint32(_sireId); + + // Trigger the cooldown for both parents. + _triggerCooldown(sire); + _triggerCooldown(matron); + + // Clear siring permission for both parents. This may not be strictly necessary + // but it's likely to avoid confusion! + delete sireAllowedToAddress[_matronId]; + delete sireAllowedToAddress[_sireId]; + + // Every time a kitty gets pregnant, counter is incremented. + pregnantKitties++; + + // Emit the pregnancy event. + emit Pregnant(kittyIndexToOwner[_matronId], _matronId, _sireId, matron.cooldownEndBlock); + } + + /// @notice Breed a Kitty you own (as matron) with a sire that you own, or for which you + /// have previously been given Siring approval. Will either make your cat pregnant, or will + /// fail entirely. Requires a pre-payment of the fee given out to the first caller of giveBirth() + /// @param _matronId The ID of the Kitty acting as matron (will end up pregnant if successful) + /// @param _sireId The ID of the Kitty acting as sire (will begin its siring cooldown if successful) + function breedWithAuto(uint256 _matronId, uint256 _sireId) + external + payable + whenNotPaused + { + // Checks for payment. + require(msg.value >= autoBirthFee); + + // Caller must own the matron. + require(_owns(msg.sender, _matronId)); + + // Neither sire nor matron are allowed to be on auction during a normal + // breeding operation, but we don't need to check that explicitly. + // For matron: The caller of this function can't be the owner of the matron + // because the owner of a Kitty on auction is the auction house, and the + // auction house will never call breedWith(). + // For sire: Similarly, a sire on auction will be owned by the auction house + // and the act of transferring ownership will have cleared any oustanding + // siring approval. + // Thus we don't need to spend gas explicitly checking to see if either cat + // is on auction. + + // Check that matron and sire are both owned by caller, or that the sire + // has given siring permission to caller (i.e. matron's owner). + // Will fail for _sireId = 0 + require(_isSiringPermitted(_sireId, _matronId)); + + // Grab a reference to the potential matron + Kitty storage matron = kitties[_matronId]; + + // Make sure matron isn't pregnant, or in the middle of a siring cooldown + require(_isReadyToBreed(matron)); + + // Grab a reference to the potential sire + Kitty storage sire = kitties[_sireId]; + + // Make sure sire isn't pregnant, or in the middle of a siring cooldown + require(_isReadyToBreed(sire)); + + // Test that these cats are a valid mating pair. + require(_isValidMatingPair( + matron, + _matronId, + sire, + _sireId + )); + + // All checks passed, kitty gets pregnant! + _breedWith(_matronId, _sireId); + } + + /// @notice Have a pregnant Kitty give birth! + /// @param _matronId A Kitty ready to give birth. + /// @return The Kitty ID of the new kitten. + /// @dev Looks at a given Kitty and, if pregnant and if the gestation period has passed, + /// combines the genes of the two parents to create a new kitten. The new Kitty is assigned + /// to the current owner of the matron. Upon successful completion, both the matron and the + /// new kitten will be ready to breed again. Note that anyone can call this function (if they + /// are willing to pay the gas!), but the new kitten always goes to the mother's owner. + function giveBirth(uint256 _matronId) + external + whenNotPaused + returns(uint256) + { + // Grab a reference to the matron in storage. + Kitty storage matron = kitties[_matronId]; + + // Check that the matron is a valid cat. + require(matron.birthTime != 0); + + // Check that the matron is pregnant, and that its time has come! + require(_isReadyToGiveBirth(matron)); + + // Grab a reference to the sire in storage. + uint256 sireId = matron.siringWithId; + Kitty storage sire = kitties[sireId]; + + // Determine the higher generation number of the two parents + uint16 parentGen = matron.generation; + if (sire.generation > matron.generation) { + parentGen = sire.generation; + } + + // Call the sooper-sekret gene mixing operation. + uint256 childGenes = geneScience.mixGenes(matron.genes, sire.genes, matron.cooldownEndBlock - 1); + + // Make the new kitten! + address owner = kittyIndexToOwner[_matronId]; + uint256 kittenId = _createKitty(_matronId, matron.siringWithId, parentGen + 1, childGenes, owner); + + // Clear the reference to sire from the matron (REQUIRED! Having siringWithId + // set is what marks a matron as being pregnant.) + delete matron.siringWithId; + + // Every time a kitty gives birth counter is decremented. + pregnantKitties--; + + // Send the balance fee to the person who made birth happen. + msg.sender.transfer(autoBirthFee); + + // return the new kitten's ID + return kittenId; + } +} + + + +/// @title Handles creating auctions for sale and siring of kitties. +/// This wrapper of ReverseAuction exists only so that users can create +/// auctions with only one transaction. +contract KittyAuction is KittyBreeding { + + // @notice The auction contract variables are defined in KittyBase to allow + // us to refer to them in KittyOwnership to prevent accidental transfers. + // `saleAuction` refers to the auction for gen0 and p2p sale of kitties. + // `siringAuction` refers to the auction for siring rights of kitties. + + /// @dev Sets the reference to the sale auction. + /// @param _address - Address of sale contract. + function setSaleAuctionAddress(address _address) external onlyCEO { + SaleClockAuction candidateContract = SaleClockAuction(_address); + + // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 + require(candidateContract.isSaleClockAuction()); + + // Set the new contract address + saleAuction = candidateContract; + } + + /// @dev Sets the reference to the siring auction. + /// @param _address - Address of siring contract. + function setSiringAuctionAddress(address _address) external onlyCEO { + SiringClockAuction candidateContract = SiringClockAuction(_address); + + // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 + require(candidateContract.isSiringClockAuction()); + + // Set the new contract address + siringAuction = candidateContract; + } + + /// @dev Put a kitty up for auction. + /// Does some ownership trickery to create auctions in one tx. + function createSaleAuction( + uint256 _kittyId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration + ) + external + whenNotPaused + { + // Auction contract checks input sizes + // If kitty is already on any auction, this will throw + // because it will be owned by the auction contract. + require(_owns(msg.sender, _kittyId)); + // Ensure the kitty is not pregnant to prevent the auction + // contract accidentally receiving ownership of the child. + // NOTE: the kitty IS allowed to be in a cooldown. + require(!isPregnant(_kittyId)); + _approve(_kittyId, address(saleAuction)); + // Sale auction throws if inputs are invalid and clears + // transfer and sire approval after escrowing the kitty. + saleAuction.createAuction( + _kittyId, + _startingPrice, + _endingPrice, + _duration, + msg.sender + ); + } + + /// @dev Put a kitty up for auction to be sire. + /// Performs checks to ensure the kitty can be sired, then + /// delegates to reverse auction. + function createSiringAuction( + uint256 _kittyId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration + ) + external + whenNotPaused + { + // Auction contract checks input sizes + // If kitty is already on any auction, this will throw + // because it will be owned by the auction contract. + require(_owns(msg.sender, _kittyId)); + require(isReadyToBreed(_kittyId)); + _approve(_kittyId, address(siringAuction)); + // Siring auction throws if inputs are invalid and clears + // transfer and sire approval after escrowing the kitty. + siringAuction.createAuction( + _kittyId, + _startingPrice, + _endingPrice, + _duration, + msg.sender + ); + } + + /// @dev Completes a siring auction by bidding. + /// Immediately breeds the winning matron with the sire on auction. + /// @param _sireId - ID of the sire on auction. + /// @param _matronId - ID of the matron owned by the bidder. + function bidOnSiringAuction( + uint256 _sireId, + uint256 _matronId + ) + external + payable + whenNotPaused + { + // Auction contract checks input sizes + require(_owns(msg.sender, _matronId)); + require(isReadyToBreed(_matronId)); + require(_canBreedWithViaAuction(_matronId, _sireId)); + + // Define the current price of the auction. + uint256 currentPrice = siringAuction.getCurrentPrice(_sireId); + require(msg.value >= currentPrice + autoBirthFee); + + // Siring auction will throw if the bid fails. + siringAuction.bid.value(msg.value - autoBirthFee)(_sireId); + _breedWith(uint32(_matronId), uint32(_sireId)); + } + + /// @dev Transfers the balance of the sale auction contract + /// to the KittyCore contract. We use two-step withdrawal to + /// prevent two transfer calls in the auction bid function. + function withdrawAuctionBalances() external onlyCLevel { + saleAuction.withdrawBalance(); + siringAuction.withdrawBalance(); + } +} + + +/// @title all functions related to creating kittens +contract KittyMinting is KittyAuction { + + // Limits the number of cats the contract owner can ever create. + uint256 public constant PROMO_CREATION_LIMIT = 5000; + uint256 public constant GEN0_CREATION_LIMIT = 45000; + + // Constants for gen0 auctions. + uint256 public constant GEN0_STARTING_PRICE = 10 sun; + uint256 public constant GEN0_AUCTION_DURATION = 1 days; + + // Counts the number of cats the contract owner has created. + uint256 public promoCreatedCount; + uint256 public gen0CreatedCount; + + /// @dev we can create promo kittens, up to a limit. Only callable by COO + /// @param _genes the encoded genes of the kitten to be created, any value is accepted + /// @param _owner the future owner of the created kittens. Default to contract COO + function createPromoKitty(uint256 _genes, address _owner) external onlyCOO { + address kittyOwner = _owner; + if (kittyOwner == address(0)) { + kittyOwner = cooAddress; + } + require(promoCreatedCount < PROMO_CREATION_LIMIT); + + promoCreatedCount++; + _createKitty(0, 0, 0, _genes, kittyOwner); + } + + /// @dev Creates a new gen0 kitty with the given genes and + /// creates an auction for it. + function createGen0Auction(uint256 _genes) external onlyCOO { + require(gen0CreatedCount < GEN0_CREATION_LIMIT); + + uint256 kittyId = _createKitty(0, 0, 0, _genes, address(this)); + _approve(kittyId, address(saleAuction)); + + saleAuction.createAuction( + kittyId, + _computeNextGen0Price(), + 0, + GEN0_AUCTION_DURATION, + address(uint160(address(this))) + ); + + gen0CreatedCount++; + } + + /// @dev Computes the next gen0 auction starting price, given + /// the average of the past 5 prices + 50%. + function _computeNextGen0Price() internal view returns (uint256) { + uint256 avePrice = saleAuction.averageGen0SalePrice(); + + // Sanity check to ensure we don't overflow arithmetic + require(avePrice == uint256(uint128(avePrice))); + + uint256 nextPrice = avePrice + (avePrice / 2); + + // We never auction for less than starting price + if (nextPrice < GEN0_STARTING_PRICE) { + nextPrice = GEN0_STARTING_PRICE; + } + + return nextPrice; + } +} + + + +/// @title CryptoKitties: Collectible, breedable, and oh-so-adorable cats on the Ethereum blockchain. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev The main CryptoKitties contract, keeps track of kittens so they don't wander around and get lost. +contract KittyCore is KittyMinting { + + // This is the main CryptoKitties contract. In order to keep our code seperated into logical sections, + // we've broken it up in two ways. First, we have several seperately-instantiated sibling contracts + // that handle auctions and our super-top-secret genetic combination algorithm. The auctions are + // seperate since their logic is somewhat complex and there's always a risk of subtle bugs. By keeping + // them in their own contracts, we can upgrade them without disrupting the main contract that tracks + // kitty ownership. The genetic combination algorithm is kept seperate so we can open-source all of + // the rest of our code without making it _too_ easy for folks to figure out how the genetics work. + // Don't worry, I'm sure someone will reverse engineer it soon enough! + // + // Secondly, we break the core contract into multiple files using inheritence, one for each major + // facet of functionality of CK. This allows us to keep related code bundled together while still + // avoiding a single giant file with everything in it. The breakdown is as follows: + // + // - KittyBase: This is where we define the most fundamental code shared throughout the core + // functionality. This includes our main data storage, constants and data types, plus + // internal functions for managing these items. + // + // - KittyAccessControl: This contract manages the various addresses and constraints for operations + // that can be executed only by specific roles. Namely CEO, CFO and COO. + // + // - KittyOwnership: This provides the methods required for basic non-fungible token + // transactions, following the draft ERC-721 spec (https://github.com/ethereum/EIPs/issues/721). + // + // - KittyBreeding: This file contains the methods necessary to breed cats together, including + // keeping track of siring offers, and relies on an external genetic combination contract. + // + // - KittyAuctions: Here we have the public methods for auctioning or bidding on cats or siring + // services. The actual auction functionality is handled in two sibling contracts (one + // for sales and one for siring), while auction creation and bidding is mostly mediated + // through this facet of the core contract. + // + // - KittyMinting: This final facet contains the functionality we use for creating new gen0 cats. + // We can make up to 5000 "promo" cats that can be given away (especially important when + // the community is new), and all others can only be created and then immediately put up + // for auction via an algorithmically determined starting price. Regardless of how they + // are created, there is a hard limit of 50k gen0 cats. After that, it's all up to the + // community to breed, breed, breed! + + // Set in case the core contract is broken and an upgrade is required + address public newContractAddress; + + /// @notice Creates the main CryptoKitties smart contract instance. + constructor() public { + // Starts paused. + paused = true; + + // the creator of the contract is the initial CEO + ceoAddress = msg.sender; + + // the creator of the contract is also the initial COO + cooAddress = msg.sender; + + // start with the mythical kitten 0 - so we don't have generation-0 parent issues + _createKitty(0, 0, 0, uint256(-1), address(0)); + } + + /// @dev Used to mark the smart contract as upgraded, in case there is a serious + /// breaking bug. This method does nothing but keep track of the new contract and + /// emit a message indicating that the new address is set. It's up to clients of this + /// contract to update to the new contract address in that case. (This contract will + /// be paused indefinitely if such an upgrade takes place.) + /// @param _v2Address new address + function setNewAddress(address _v2Address) external onlyCEO whenPaused { + // See README.md for updgrade plan + newContractAddress = _v2Address; + emit ContractUpgrade(_v2Address); + } + + /// @notice No tipping! + /// @dev Reject all Ether from being sent here, unless it's from one of the + /// two auction contracts. (Hopefully, we can prevent user accidents.) + function() external payable { + require( + msg.sender == address(saleAuction) || + msg.sender == address(siringAuction) + ); + } + + /// @notice Returns all the relevant information about a specific kitty. + /// @param _id The ID of the kitty of interest. + function getKitty(uint256 _id) + external + view + returns ( + bool isGestating, + bool isReady, + uint256 cooldownIndex, + uint256 nextActionAt, + uint256 siringWithId, + uint256 birthTime, + uint256 matronId, + uint256 sireId, + uint256 generation, + uint256 genes + ) { + Kitty storage kit = kitties[_id]; + + // if this variable is 0 then it's not gestating + isGestating = (kit.siringWithId != 0); + isReady = (kit.cooldownEndBlock <= block.number); + cooldownIndex = uint256(kit.cooldownIndex); + nextActionAt = uint256(kit.cooldownEndBlock); + siringWithId = uint256(kit.siringWithId); + birthTime = uint256(kit.birthTime); + matronId = uint256(kit.matronId); + sireId = uint256(kit.sireId); + generation = uint256(kit.generation); + genes = kit.genes; + } + + /// @dev Override unpause so it requires all external contract addresses + /// to be set before contract can be unpaused. Also, we can't have + /// newContractAddress set either, because then the contract was upgraded. + /// @notice This is public rather than external so we can call super.unpause + /// without using an expensive CALL. + + function unpause(address payable toAddress, uint256 tokenValue, trcToken tokenId) public onlyCEO whenPaused returns (uint256 r) { + require(address(saleAuction) != address(0)); + require(address(siringAuction) != address(0)); + require(address(geneScience) != address(0)); + require(address(newContractAddress) == address(0)); + toAddress.transferToken(tokenValue, tokenId); + r = address(this).tokenBalance(tokenId); + // Actually unpause the contract. + super.unpause(); + } + + // @dev Allows the CFO to capture the balance available to the contract. + function withdrawBalance() external onlyCFO { + uint256 balance = address(this).balance; + // Subtract all the currently pregnant kittens we have, plus 1 of margin. + uint256 subtractFees = (pregnantKitties + 1) * autoBirthFee; + + if (balance > subtractFees) { + cfoAddress.transfer(balance - subtractFees); + } + } +} + + + + + + + + + + + + + +// // Auction wrapper functions + + +// Auction wrapper functions + + + + + + + +/// @title SEKRETOOOO +contract GeneScienceInterface { + + function isGeneScience() public pure returns (bool){ + return true; + } + + /// @dev given genes of kitten 1 & 2, return a genetic combination - may have a random factor + /// @param genes1 genes of mom + /// @param genes2 genes of sire + /// @return the genes that are supposed to be passed down the child + function mixGenes(uint256 genes1, uint256 genes2, uint256 targetBlock) public pure returns (uint256){ + + return (genes1+genes2+targetBlock)/2; + + +} +} + + + + + + + + + + + + + + + + +/// @title The external contract that is responsible for generating metadata for the kitties, +/// it has one function that will return the data as bytes. +contract ERC721Metadata { + /// @dev Given a token Id, returns a byte array that is supposed to be converted into string. + function getMetadata(uint256 _tokenId, string memory) public view returns (bytes32[4] memory buffer, uint256 count) { + if (_tokenId == 1) { + buffer[0] = "Hello World! :D"; + count = 15; + } else if (_tokenId == 2) { + buffer[0] = "I would definitely choose a medi"; + buffer[1] = "um length string."; + count = 49; + } else if (_tokenId == 3) { + buffer[0] = "Lorem ipsum dolor sit amet, mi e"; + buffer[1] = "st accumsan dapibus augue lorem,"; + buffer[2] = " tristique vestibulum id, libero"; + buffer[3] = " suscipit varius sapien aliquam."; + count = 128; + } + } +} + + + + + + + + + + + + + + + +/// @title Auction Core +/// @dev Contains models, variables, and internal methods for the auction. +/// @notice We omit a fallback function to prevent accidental sends to this contract. +contract ClockAuctionBase { + + // Represents an auction on an NFT + struct Auction { + // Current owner of NFT + address payable seller; + // Price (in wei) at beginning of auction + uint128 startingPrice; + // Price (in wei) at end of auction + uint128 endingPrice; + // Duration (in seconds) of auction + uint64 duration; + // Time when auction started + // NOTE: 0 if this auction has been concluded + uint64 startedAt; + } + + // Reference to contract tracking NFT ownership + ERC721 public nonFungibleContract; + + // Cut owner takes on each auction, measured in basis points (1/100 of a percent). + // Values 0-10,000 map to 0%-100% + uint256 public ownerCut; + + // Map from token ID to their corresponding auction. + mapping (uint256 => Auction) tokenIdToAuction; + + event AuctionCreated(uint256 tokenId, uint256 startingPrice, uint256 endingPrice, uint256 duration); + event AuctionSuccessful(uint256 tokenId, uint256 totalPrice, address winner); + event AuctionCancelled(uint256 tokenId); + + /// @dev Returns true if the claimant owns the token. + /// @param _claimant - Address claiming to own the token. + /// @param _tokenId - ID of token whose ownership to verify. + function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { + return (nonFungibleContract.ownerOf(_tokenId) == _claimant); + } + + /// @dev Escrows the NFT, assigning ownership to this contract. + /// Throws if the escrow fails. + /// @param _owner - Current owner address of token to escrow. + /// @param _tokenId - ID of token whose approval to verify. + function _escrow(address _owner, uint256 _tokenId) internal { + // it will throw if transfer fails + nonFungibleContract.transferFrom(_owner, address(this), _tokenId); + } + + /// @dev Transfers an NFT owned by this contract to another address. + /// Returns true if the transfer succeeds. + /// @param _receiver - Address to transfer NFT to. + /// @param _tokenId - ID of token to transfer. + function _transfer(address _receiver, uint256 _tokenId) internal { + // it will throw if transfer fails + nonFungibleContract.transfer(_receiver, _tokenId); + } + + /// @dev Adds an auction to the list of open auctions. Also fires the + /// AuctionCreated event. + /// @param _tokenId The ID of the token to be put on auction. + /// @param _auction Auction to add. + function _addAuction(uint256 _tokenId, Auction memory _auction) internal { + // Require that all auctions have a duration of + // at least one minute. (Keeps our math from getting hairy!) + require(_auction.duration >= 1 minutes); + + tokenIdToAuction[_tokenId] = _auction; + + emit AuctionCreated( + uint256(_tokenId), + uint256(_auction.startingPrice), + uint256(_auction.endingPrice), + uint256(_auction.duration) + ); + } + + /// @dev Cancels an auction unconditionally. + function _cancelAuction(uint256 _tokenId, address _seller) internal { + _removeAuction(_tokenId); + _transfer(_seller, _tokenId); + emit AuctionCancelled(_tokenId); + } + + /// @dev Computes the price and transfers winnings. + /// Does NOT transfer ownership of token. + function _bid(uint256 _tokenId, uint256 _bidAmount) + internal + returns (uint256) + { + // Get a reference to the auction struct + Auction storage auction = tokenIdToAuction[_tokenId]; + + // Explicitly check that this auction is currently live. + // (Because of how Ethereum mappings work, we can't just count + // on the lookup above failing. An invalid _tokenId will just + // return an auction object that is all zeros.) + require(_isOnAuction(auction)); + + // Check that the bid is greater than or equal to the current price + uint256 price = _currentPrice(auction); + require(_bidAmount >= price); + + // Grab a reference to the seller before the auction struct + // gets deleted. + address payable seller = auction.seller; + + // The bid is good! Remove the auction before sending the fees + // to the sender so we can't have a reentrancy attack. + _removeAuction(_tokenId); + + // Transfer proceeds to seller (if there are any!) + if (price > 0) { + // Calculate the auctioneer's cut. + // (NOTE: _computeCut() is guaranteed to return a + // value <= price, so this subtraction can't go negative.) + uint256 auctioneerCut = _computeCut(price); + uint256 sellerProceeds = price - auctioneerCut; + + // NOTE: Doing a transfer() in the middle of a complex + // method like this is generally discouraged because of + // reentrancy attacks and DoS attacks if the seller is + // a contract with an invalid fallback function. We explicitly + // guard against reentrancy attacks by removing the auction + // before calling transfer(), and the only thing the seller + // can DoS is the sale of their own asset! (And if it's an + // accident, they can call cancelAuction(). ) + seller.transfer(sellerProceeds); + } + + // Calculate any excess funds included with the bid. If the excess + // is anything worth worrying about, transfer it back to bidder. + // NOTE: We checked above that the bid amount is greater than or + // equal to the price so this cannot underflow. + uint256 bidExcess = _bidAmount - price; + + // Return the funds. Similar to the previous transfer, this is + // not susceptible to a re-entry attack because the auction is + // removed before any transfers occur. + msg.sender.transfer(bidExcess); + + // Tell the world! + emit AuctionSuccessful(_tokenId, price, msg.sender); + + return price; + } + + /// @dev Removes an auction from the list of open auctions. + /// @param _tokenId - ID of NFT on auction. + function _removeAuction(uint256 _tokenId) internal { + delete tokenIdToAuction[_tokenId]; + } + + /// @dev Returns true if the NFT is on auction. + /// @param _auction - Auction to check. + function _isOnAuction(Auction storage _auction) internal view returns (bool) { + return (_auction.startedAt > 0); + } + + /// @dev Returns current price of an NFT on auction. Broken into two + /// functions (this one, that computes the duration from the auction + /// structure, and the other that does the price computation) so we + /// can easily test that the price computation works correctly. + function _currentPrice(Auction storage _auction) + internal + view + returns (uint256) + { + uint256 secondsPassed = 0; + + // A bit of insurance against negative values (or wraparound). + // Probably not necessary (since Ethereum guarnatees that the + // now variable doesn't ever go backwards). + if (now > _auction.startedAt) { + secondsPassed = now - _auction.startedAt; + } + + return _computeCurrentPrice( + _auction.startingPrice, + _auction.endingPrice, + _auction.duration, + secondsPassed + ); + } + + /// @dev Computes the current price of an auction. Factored out + /// from _currentPrice so we can run extensive unit tests. + /// When testing, make this function public and turn on + /// `Current price computation` test suite. + function _computeCurrentPrice( + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration, + uint256 _secondsPassed + ) + internal + pure + returns (uint256) + { + // NOTE: We don't use SafeMath (or similar) in this function because + // all of our public functions carefully cap the maximum values for + // time (at 64-bits) and currency (at 128-bits). _duration is + // also known to be non-zero (see the require() statement in + // _addAuction()) + if (_secondsPassed >= _duration) { + // We've reached the end of the dynamic pricing portion + // of the auction, just return the end price. + return _endingPrice; + } else { + // Starting price can be higher than ending price (and often is!), so + // this delta can be negative. + int256 totalPriceChange = int256(_endingPrice) - int256(_startingPrice); + + // This multiplication can't overflow, _secondsPassed will easily fit within + // 64-bits, and totalPriceChange will easily fit within 128-bits, their product + // will always fit within 256-bits. + int256 currentPriceChange = totalPriceChange * int256(_secondsPassed) / int256(_duration); + + // currentPriceChange can be negative, but if so, will have a magnitude + // less that _startingPrice. Thus, this result will always end up positive. + int256 currentPrice = int256(_startingPrice) + currentPriceChange; + + return uint256(currentPrice); + } + } + + /// @dev Computes owner's cut of a sale. + /// @param _price - Sale price of NFT. + function _computeCut(uint256 _price) internal view returns (uint256) { + // NOTE: We don't use SafeMath (or similar) in this function because + // all of our entry functions carefully cap the maximum values for + // currency (at 128-bits), and ownerCut <= 10000 (see the require() + // statement in the ClockAuction constructor). The result of this + // function is always guaranteed to be <= _price. + return _price * ownerCut / 10000; + } + +} + + + + + + + +/** + * @title Pausable + * @dev Base contract which allows children to implement an emergency stop mechanism. + */ +contract Pausable is Ownable { + event Pause(); + event Unpause(); + + bool public paused = false; + + + /** + * @dev modifier to allow actions only when the contract IS paused + */ + modifier whenNotPaused() { + require(!paused); + _; + } + + /** + * @dev modifier to allow actions only when the contract IS NOT paused + */ + modifier whenPaused { + require(paused); + _; + } + + /** + * @dev called by the owner to pause, triggers stopped state + */ + function pause() onlyOwner whenNotPaused public returns (bool) { + paused = true; + emit Pause(); + return true; + } + + /** + * @dev called by the owner to unpause, returns to normal state + */ + function unpause() onlyOwner whenPaused public returns (bool) { + paused = false; + emit Unpause(); + return true; + } +} + + +/// @title Clock auction for non-fungible tokens. +/// @notice We omit a fallback function to prevent accidental sends to this contract. +contract ClockAuction is Pausable, ClockAuctionBase { + + /// @dev The ERC-165 interface signature for ERC-721. + /// Ref: https://github.com/ethereum/EIPs/issues/165 + /// Ref: https://github.com/ethereum/EIPs/issues/721 + bytes4 constant InterfaceSignature_ERC721 = bytes4(0x9a20483d); + + /// @dev Constructor creates a reference to the NFT ownership contract + /// and verifies the owner cut is in the valid range. + /// @param _nftAddress - address of a deployed contract implementing + /// the Nonfungible Interface. + /// @param _cut - percent cut the owner takes on each auction, must be + /// between 0-10,000. + constructor(address _nftAddress, uint256 _cut) public { + require(_cut <= 10000); + ownerCut = _cut; + + ERC721 candidateContract = ERC721(_nftAddress); + require(candidateContract.supportsInterface(InterfaceSignature_ERC721)); + nonFungibleContract = candidateContract; + } + + /// @dev Remove all Ether from the contract, which is the owner's cuts + /// as well as any Ether sent directly to the contract address. + /// Always transfers to the NFT contract, but can be called either by + /// the owner or the NFT contract. + function withdrawBalance() external { + address payable nftAddress = address(uint160(address(nonFungibleContract))); + + require( + msg.sender == owner || + msg.sender == nftAddress + ); + // We are using this boolean method to make sure that even if one fails it will still work + bool res = nftAddress.send(address(this).balance); + } + + /// @dev Creates and begins a new auction. + /// @param _tokenId - ID of token to auction, sender must be owner. + /// @param _startingPrice - Price of item (in wei) at beginning of auction. + /// @param _endingPrice - Price of item (in wei) at end of auction. + /// @param _duration - Length of time to move between starting + /// price and ending price (in seconds). + /// @param _seller - Seller, if not the message sender + function createAuction( + uint256 _tokenId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration, + address payable _seller + ) + external + whenNotPaused + { + // Sanity check that no inputs overflow how many bits we've allocated + // to store them in the auction struct. + require(_startingPrice == uint256(uint128(_startingPrice))); + require(_endingPrice == uint256(uint128(_endingPrice))); + require(_duration == uint256(uint64(_duration))); + + require(_owns(msg.sender, _tokenId)); + _escrow(msg.sender, _tokenId); + Auction memory auction = Auction( + _seller, + uint128(_startingPrice), + uint128(_endingPrice), + uint64(_duration), + uint64(now) + ); + _addAuction(_tokenId, auction); + } + + /// @dev Bids on an open auction, completing the auction and transferring + /// ownership of the NFT if enough Ether is supplied. + /// @param _tokenId - ID of token to bid on. + function bid(uint256 _tokenId) + external + payable + whenNotPaused + { + // _bid will throw if the bid or funds transfer fails + _bid(_tokenId, msg.value); + _transfer(msg.sender, _tokenId); + } + + /// @dev Cancels an auction that hasn't been won yet. + /// Returns the NFT to original owner. + /// @notice This is a state-modifying function that can + /// be called while the contract is paused. + /// @param _tokenId - ID of token on auction + function cancelAuction(uint256 _tokenId) + external + { + Auction storage auction = tokenIdToAuction[_tokenId]; + require(_isOnAuction(auction)); + address seller = auction.seller; + require(msg.sender == seller); + _cancelAuction(_tokenId, seller); + } + + /// @dev Cancels an auction when the contract is paused. + /// Only the owner may do this, and NFTs are returned to + /// the seller. This should only be used in emergencies. + /// @param _tokenId - ID of the NFT on auction to cancel. + function cancelAuctionWhenPaused(uint256 _tokenId) + whenPaused + onlyOwner + external + { + Auction storage auction = tokenIdToAuction[_tokenId]; + require(_isOnAuction(auction)); + _cancelAuction(_tokenId, auction.seller); + } + + /// @dev Returns auction info for an NFT on auction. + /// @param _tokenId - ID of NFT on auction. + function getAuction(uint256 _tokenId) + external + view + returns + ( + address seller, + uint256 startingPrice, + uint256 endingPrice, + uint256 duration, + uint256 startedAt + ) { + Auction storage auction = tokenIdToAuction[_tokenId]; + require(_isOnAuction(auction)); + return ( + auction.seller, + auction.startingPrice, + auction.endingPrice, + auction.duration, + auction.startedAt + ); + } + + /// @dev Returns the current price of an auction. + /// @param _tokenId - ID of the token price we are checking. + function getCurrentPrice(uint256 _tokenId) + external + view + returns (uint256) + { + Auction storage auction = tokenIdToAuction[_tokenId]; + require(_isOnAuction(auction)); + return _currentPrice(auction); + } + +} + + +/// @title Reverse auction modified for siring +/// @notice We omit a fallback function to prevent accidental sends to this contract. +contract SiringClockAuction is ClockAuction { + + // @dev Sanity check that allows us to ensure that we are pointing to the + // right auction in our setSiringAuctionAddress() call. + bool public isSiringClockAuction = true; + + // Delegate constructor + constructor(address _nftAddr, uint256 _cut) public + ClockAuction(_nftAddr, _cut) {} + + /// @dev Creates and begins a new auction. Since this function is wrapped, + /// require sender to be KittyCore contract. + /// @param _tokenId - ID of token to auction, sender must be owner. + /// @param _startingPrice - Price of item (in wei) at beginning of auction. + /// @param _endingPrice - Price of item (in wei) at end of auction. + /// @param _duration - Length of auction (in seconds). + /// @param _seller - Seller, if not the message sender + function createAuction( + uint256 _tokenId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration, + address payable _seller + ) + external + { + // Sanity check that no inputs overflow how many bits we've allocated + // to store them in the auction struct. + require(_startingPrice == uint256(uint128(_startingPrice))); + require(_endingPrice == uint256(uint128(_endingPrice))); + require(_duration == uint256(uint64(_duration))); + + require(msg.sender == address(nonFungibleContract)); + _escrow(_seller, _tokenId); + Auction memory auction = Auction( + _seller, + uint128(_startingPrice), + uint128(_endingPrice), + uint64(_duration), + uint64(now) + ); + _addAuction(_tokenId, auction); + } + + /// @dev Places a bid for siring. Requires the sender + /// is the KittyCore contract because all bid methods + /// should be wrapped. Also returns the kitty to the + /// seller rather than the winner. + function bid(uint256 _tokenId) + external + payable + { + require(msg.sender == address(nonFungibleContract)); + address seller = tokenIdToAuction[_tokenId].seller; + // _bid checks that token ID is valid and will throw if bid fails + _bid(_tokenId, msg.value); + // We transfer the kitty back to the seller, the winner will get + // the offspring + _transfer(seller, _tokenId); + } + +} + + + + + +/// @title Clock auction modified for sale of kitties +/// @notice We omit a fallback function to prevent accidental sends to this contract. +contract SaleClockAuction is ClockAuction { + + // @dev Sanity check that allows us to ensure that we are pointing to the + // right auction in our setSaleAuctionAddress() call. + bool public isSaleClockAuction = true; + + // Tracks last 5 sale price of gen0 kitty sales + uint256 public gen0SaleCount; + uint256[5] public lastGen0SalePrices; + + // Delegate constructor + constructor(address _nftAddr, uint256 _cut) public + ClockAuction(_nftAddr, _cut) {} + + /// @dev Creates and begins a new auction. + /// @param _tokenId - ID of token to auction, sender must be owner. + /// @param _startingPrice - Price of item (in wei) at beginning of auction. + /// @param _endingPrice - Price of item (in wei) at end of auction. + /// @param _duration - Length of auction (in seconds). + /// @param _seller - Seller, if not the message sender + function createAuction( + uint256 _tokenId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration, + address payable _seller + ) + external + { + // Sanity check that no inputs overflow how many bits we've allocated + // to store them in the auction struct. + require(_startingPrice == uint256(uint128(_startingPrice))); + require(_endingPrice == uint256(uint128(_endingPrice))); + require(_duration == uint256(uint64(_duration))); + + require(msg.sender == address(nonFungibleContract)); + _escrow(_seller, _tokenId); + Auction memory auction = Auction( + _seller, + uint128(_startingPrice), + uint128(_endingPrice), + uint64(_duration), + uint64(now) + ); + _addAuction(_tokenId, auction); + } + + /// @dev Updates lastSalePrice if seller is the nft contract + /// Otherwise, works the same as default bid method. + function bid(uint256 _tokenId) + external + payable + { + // _bid verifies token ID size + address seller = tokenIdToAuction[_tokenId].seller; + uint256 price = _bid(_tokenId, msg.value); + _transfer(msg.sender, _tokenId); + + // If not a gen0 auction, exit + if (seller == address(nonFungibleContract)) { + // Track gen0 sale prices + lastGen0SalePrices[gen0SaleCount % 5] = price; + gen0SaleCount++; + } + } + + function averageGen0SalePrice() external view returns (uint256) { + uint256 sum = 0; + for (uint256 i = 0; i < 5; i++) { + sum += lastGen0SalePrices[i]; + } + return sum / 5; + } + +} + + + + + + + diff --git a/src/test/resources/soliditycode/addTrcToken002Cat_withFinny.sol b/src/test/resources/soliditycode/addTrcToken002Cat_withFinny.sol new file mode 100644 index 00000000000..2acebceddda --- /dev/null +++ b/src/test/resources/soliditycode/addTrcToken002Cat_withFinny.sol @@ -0,0 +1,2051 @@ +//pragma solidity ^0.4.11; + + +/** + * @title Ownable + * @dev The Ownable contract has an owner address, and provides basic authorization control + * functions, this simplifies the implementation of "user permissions". + */ +contract Ownable { + address public owner; + + + /** + * @dev The Ownable constructor sets the original `owner` of the contract to the sender + * account. + */ + constructor() public { + owner = msg.sender; + } + + + /** + * @dev Throws if called by any account other than the owner. + */ + modifier onlyOwner() { + require(msg.sender == owner); + _; + } + + + /** + * @dev Allows the current owner to transfer control of the contract to a newOwner. + * @param newOwner The address to transfer ownership to. + */ + function transferOwnership(address newOwner) public onlyOwner { + if (newOwner != address(0)) { + owner = newOwner; + } + } + +} + + + + +/// @title A facet of KittyCore that manages special access privileges. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. +contract KittyAccessControl { + // This facet controls access control for CryptoKitties. There are four roles managed here: + // + // - The CEO: The CEO can reassign other roles and change the addresses of our dependent smart + // contracts. It is also the only role that can unpause the smart contract. It is initially + // set to the address that created the smart contract in the KittyCore constructor. + // + // - The CFO: The CFO can withdraw funds from KittyCore and its auction contracts. + // + // - The COO: The COO can release gen0 kitties to auction, and mint promo cats. + // + // It should be noted that these roles are distinct without overlap in their access abilities, the + // abilities listed for each role above are exhaustive. In particular, while the CEO can assign any + // address to any role, the CEO address itself doesn't have the ability to act in those roles. This + // restriction is intentional so that we aren't tempted to use the CEO address frequently out of + // convenience. The less we use an address, the less likely it is that we somehow compromise the + // account. + + /// @dev Emited when contract is upgraded - See README.md for updgrade plan + event ContractUpgrade(address newContract); + + // The addresses of the accounts (or contracts) that can execute actions within each roles. + address public ceoAddress; + address payable public cfoAddress; + address public cooAddress; + + // @dev Keeps track whether the contract is paused. When that is true, most actions are blocked + bool public paused = false; + + /// @dev Access modifier for CEO-only functionality + modifier onlyCEO() { + require(msg.sender == ceoAddress); + _; + } + + /// @dev Access modifier for CFO-only functionality + modifier onlyCFO() { + require(msg.sender == cfoAddress); + _; + } + + /// @dev Access modifier for COO-only functionality + modifier onlyCOO() { + require(msg.sender == cooAddress); + _; + } + + modifier onlyCLevel() { + require( + msg.sender == cooAddress || + msg.sender == ceoAddress || + msg.sender == cfoAddress + ); + _; + } + + /// @dev Assigns a new address to act as the CEO. Only available to the current CEO. + /// @param _newCEO The address of the new CEO + function setCEO(address _newCEO) external onlyCEO { + require(_newCEO != address(0)); + + ceoAddress = _newCEO; + } + + /// @dev Assigns a new address to act as the CFO. Only available to the current CEO. + /// @param _newCFO The address of the new CFO + function setCFO(address payable _newCFO) external onlyCEO { + require(_newCFO != address(0)); + + cfoAddress = _newCFO; + } + + /// @dev Assigns a new address to act as the COO. Only available to the current CEO. + /// @param _newCOO The address of the new COO + function setCOO(address _newCOO) external onlyCEO { + require(_newCOO != address(0)); + + cooAddress = _newCOO; + } + + /*** Pausable functionality adapted from OpenZeppelin ***/ + + /// @dev Modifier to allow actions only when the contract IS NOT paused + modifier whenNotPaused() { + require(!paused); + _; + } + + /// @dev Modifier to allow actions only when the contract IS paused + modifier whenPaused { + require(paused); + _; + } + + /// @dev Called by any "C-level" role to pause the contract. Used only when + /// a bug or exploit is detected and we need to limit damage. + function pause() external onlyCLevel whenNotPaused { + paused = true; + } + + /// @dev Unpauses the smart contract. Can only be called by the CEO, since + /// one reason we may pause the contract is when CFO or COO accounts are + /// compromised. + /// @notice This is public rather than external so it can be called by + /// derived contracts. + function unpause() public onlyCEO whenPaused { + // can't unpause if contract was upgraded + paused = false; + } +} + + + + +/// @title Base contract for CryptoKitties. Holds all common structs, events and base variables. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. +contract KittyBase is KittyAccessControl { + /*** EVENTS ***/ + + /// @dev The Birth event is fired whenever a new kitten comes into existence. This obviously + /// includes any time a cat is created through the giveBirth method, but it is also called + /// when a new gen0 cat is created. + event Birth(address owner, uint256 kittyId, uint256 matronId, uint256 sireId, uint256 genes); + + /// @dev Transfer event as defined in current draft of ERC721. Emitted every time a kitten + /// ownership is assigned, including births. + event Transfer(address from, address to, uint256 tokenId); + + /*** DATA TYPES ***/ + + /// @dev The main Kitty struct. Every cat in CryptoKitties is represented by a copy + /// of this structure, so great care was taken to ensure that it fits neatly into + /// exactly two 256-bit words. Note that the order of the members in this structure + /// is important because of the byte-packing rules used by Ethereum. + /// Ref: http://solidity.readthedocs.io/en/develop/miscellaneous.html + struct Kitty { + // The Kitty's genetic code is packed into these 256-bits, the format is + // sooper-sekret! A cat's genes never change. + uint256 genes; + + // The timestamp from the block when this cat came into existence. + uint64 birthTime; + + // The minimum timestamp after which this cat can engage in breeding + // activities again. This same timestamp is used for the pregnancy + // timer (for matrons) as well as the siring cooldown. + uint64 cooldownEndBlock; + + // The ID of the parents of this kitty, set to 0 for gen0 cats. + // Note that using 32-bit unsigned integers limits us to a "mere" + // 4 billion cats. This number might seem small until you realize + // that Ethereum currently has a limit of about 500 million + // transactions per year! So, this definitely won't be a problem + // for several years (even as Ethereum learns to scale). + uint32 matronId; + uint32 sireId; + + // Set to the ID of the sire cat for matrons that are pregnant, + // zero otherwise. A non-zero value here is how we know a cat + // is pregnant. Used to retrieve the genetic material for the new + // kitten when the birth transpires. + uint32 siringWithId; + + // Set to the index in the cooldown array (see below) that represents + // the current cooldown duration for this Kitty. This starts at zero + // for gen0 cats, and is initialized to floor(generation/2) for others. + // Incremented by one for each successful breeding action, regardless + // of whether this cat is acting as matron or sire. + uint16 cooldownIndex; + + // The "generation number" of this cat. Cats minted by the CK contract + // for sale are called "gen0" and have a generation number of 0. The + // generation number of all other cats is the larger of the two generation + // numbers of their parents, plus one. + // (i.e. max(matron.generation, sire.generation) + 1) + uint16 generation; + } + + /*** CONSTANTS ***/ + + /// @dev A lookup table indicating the cooldown duration after any successful + /// breeding action, called "pregnancy time" for matrons and "siring cooldown" + /// for sires. Designed such that the cooldown roughly doubles each time a cat + /// is bred, encouraging owners not to just keep breeding the same cat over + /// and over again. Caps out at one week (a cat can breed an unbounded number + /// of times, and the maximum cooldown is always seven days). + uint32[14] public cooldowns = [ + uint32(1 minutes), + uint32(2 minutes), + uint32(5 minutes), + uint32(10 minutes), + uint32(30 minutes), + uint32(1 hours), + uint32(2 hours), + uint32(4 hours), + uint32(8 hours), + uint32(16 hours), + uint32(1 days), + uint32(2 days), + uint32(4 days), + uint32(7 days) + ]; + + // An approximation of currently how many seconds are in between blocks. + uint256 public secondsPerBlock = 15; + + /*** STORAGE ***/ + + /// @dev An array containing the Kitty struct for all Kitties in existence. The ID + /// of each cat is actually an index into this array. Note that ID 0 is a negacat, + /// the unKitty, the mythical beast that is the parent of all gen0 cats. A bizarre + /// creature that is both matron and sire... to itself! Has an invalid genetic code. + /// In other words, cat ID 0 is invalid... ;-) + Kitty[] kitties; + + /// @dev A mapping from cat IDs to the address that owns them. All cats have + /// some valid owner address, even gen0 cats are created with a non-zero owner. + mapping (uint256 => address) public kittyIndexToOwner; + + // @dev A mapping from owner address to count of tokens that address owns. + // Used internally inside balanceOf() to resolve ownership count. + mapping (address => uint256) ownershipTokenCount; + + /// @dev A mapping from KittyIDs to an address that has been approved to call + /// transferFrom(). Each Kitty can only have one approved address for transfer + /// at any time. A zero value means no approval is outstanding. + mapping (uint256 => address) public kittyIndexToApproved; + + /// @dev A mapping from KittyIDs to an address that has been approved to use + /// this Kitty for siring via breedWith(). Each Kitty can only have one approved + /// address for siring at any time. A zero value means no approval is outstanding. + mapping (uint256 => address) public sireAllowedToAddress; + + /// @dev The address of the ClockAuction contract that handles sales of Kitties. This + /// same contract handles both peer-to-peer sales as well as the gen0 sales which are + /// initiated every 15 minutes. + SaleClockAuction public saleAuction; + + /// @dev The address of a custom ClockAuction subclassed contract that handles siring + /// auctions. Needs to be separate from saleAuction because the actions taken on success + /// after a sales and siring auction are quite different. + SiringClockAuction public siringAuction; + + /// @dev Assigns ownership of a specific Kitty to an address. + function _transfer(address _from, address _to, uint256 _tokenId) internal { + // Since the number of kittens is capped to 2^32 we can't overflow this + ownershipTokenCount[_to]++; + // transfer ownership + kittyIndexToOwner[_tokenId] = _to; + // When creating new kittens _from is 0x0, but we can't account that address. + if (_from != address(0)) { + ownershipTokenCount[_from]--; + // once the kitten is transferred also clear sire allowances + delete sireAllowedToAddress[_tokenId]; + // clear any previously approved ownership exchange + delete kittyIndexToApproved[_tokenId]; + } + // Emit the transfer event. + emit Transfer(_from, _to, _tokenId); + } + + /// @dev An internal method that creates a new kitty and stores it. This + /// method doesn't do any checking and should only be called when the + /// input data is known to be valid. Will generate both a Birth event + /// and a Transfer event. + /// @param _matronId The kitty ID of the matron of this cat (zero for gen0) + /// @param _sireId The kitty ID of the sire of this cat (zero for gen0) + /// @param _generation The generation number of this cat, must be computed by caller. + /// @param _genes The kitty's genetic code. + /// @param _owner The inital owner of this cat, must be non-zero (except for the unKitty, ID 0) + function _createKitty( + uint256 _matronId, + uint256 _sireId, + uint256 _generation, + uint256 _genes, + address _owner + ) + internal + returns (uint) + { + // These requires are not strictly necessary, our calling code should make + // sure that these conditions are never broken. However! _createKitty() is already + // an expensive call (for storage), and it doesn't hurt to be especially careful + // to ensure our data structures are always valid. + require(_matronId == uint256(uint32(_matronId))); + require(_sireId == uint256(uint32(_sireId))); + require(_generation == uint256(uint16(_generation))); + + // New kitty starts with the same cooldown as parent gen/2 + uint16 cooldownIndex = uint16(_generation / 2); + if (cooldownIndex > 13) { + cooldownIndex = 13; + } + + Kitty memory _kitty = Kitty({ + genes: _genes, + birthTime: uint64(now), + cooldownEndBlock: 0, + matronId: uint32(_matronId), + sireId: uint32(_sireId), + siringWithId: 0, + cooldownIndex: cooldownIndex, + generation: uint16(_generation) + }); + uint256 newKittenId = kitties.push(_kitty) - 1; + + // It's probably never going to happen, 4 billion cats is A LOT, but + // let's just be 100% sure we never let this happen. + require(newKittenId == uint256(uint32(newKittenId))); + + // emit the birth event + emit Birth( + _owner, + newKittenId, + uint256(_kitty.matronId), + uint256(_kitty.sireId), + _kitty.genes + ); + + // This will assign ownership, and also emit the Transfer event as + // per ERC721 draft + _transfer(address(0), _owner, newKittenId); + + return newKittenId; + } + + // Any C-level can fix how many seconds per blocks are currently observed. + function setSecondsPerBlock(uint256 secs) external onlyCLevel { + require(secs < cooldowns[0]); + secondsPerBlock = secs; + } +} + + +/// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens +/// @author Dieter Shirley (https://github.com/dete) +contract ERC721 { + // Required methods + function totalSupply() public view returns (uint256 total); + function balanceOf(address _owner) public view returns (uint256 balance); + function ownerOf(uint256 _tokenId) external view returns (address owner); + function approve(address _to, uint256 _tokenId) external; + function transfer(address _to, uint256 _tokenId) external; + function transferFrom(address _from, address _to, uint256 _tokenId) external; + + // Events + event Transfer(address from, address to, uint256 tokenId); + event Approval(address owner, address approved, uint256 tokenId); + + // Optional + // function name() public view returns (string name); + // function symbol() public view returns (string symbol); + // function tokensOfOwner(address _owner) external view returns (uint256[] tokenIds); + // function tokenMetadata(uint256 _tokenId, string _preferredTransport) public view returns (string infoUrl); + + // ERC-165 Compatibility (https://github.com/ethereum/EIPs/issues/165) + function supportsInterface(bytes4 _interfaceID) external view returns (bool); +} + + +/// @title The facet of the CryptoKitties core contract that manages ownership, ERC-721 (draft) compliant. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev Ref: https://github.com/ethereum/EIPs/issues/721 +/// See the KittyCore contract documentation to understand how the various contract facets are arranged. +contract KittyOwnership is ERC721, KittyBase { + + /// @notice Name and symbol of the non fungible token, as defined in ERC721. + string public constant name = "CryptoKitties"; + string public constant symbol = "CK"; + + // The contract that will return kitty metadata + ERC721Metadata public erc721Metadata; + + bytes4 constant InterfaceSignature_ERC165 = + bytes4(keccak256('supportsInterface(bytes4)')); + + bytes4 constant InterfaceSignature_ERC721 = + bytes4(keccak256('name()')) ^ + bytes4(keccak256('symbol()')) ^ + bytes4(keccak256('totalSupply()')) ^ + bytes4(keccak256('balanceOf(address)')) ^ + bytes4(keccak256('ownerOf(uint256)')) ^ + bytes4(keccak256('approve(address,uint256)')) ^ + bytes4(keccak256('transfer(address,uint256)')) ^ + bytes4(keccak256('transferFrom(address,address,uint256)')) ^ + bytes4(keccak256('tokensOfOwner(address)')) ^ + bytes4(keccak256('tokenMetadata(uint256,string)')); + + /// @notice Introspection interface as per ERC-165 (https://github.com/ethereum/EIPs/issues/165). + /// Returns true for any standardized interfaces implemented by this contract. We implement + /// ERC-165 (obviously!) and ERC-721. + function supportsInterface(bytes4 _interfaceID) external view returns (bool) + { + // DEBUG ONLY + //require((InterfaceSignature_ERC165 == 0x01ffc9a7) && (InterfaceSignature_ERC721 == 0x9a20483d)); + + return ((_interfaceID == InterfaceSignature_ERC165) || (_interfaceID == InterfaceSignature_ERC721)); + } + + /// @dev Set the address of the sibling contract that tracks metadata. + /// CEO only. + function setMetadataAddress(address _contractAddress) public onlyCEO { + erc721Metadata = ERC721Metadata(_contractAddress); + } + + // Internal utility functions: These functions all assume that their input arguments + // are valid. We leave it to public methods to sanitize their inputs and follow + // the required logic. + + /// @dev Checks if a given address is the current owner of a particular Kitty. + /// @param _claimant the address we are validating against. + /// @param _tokenId kitten id, only valid when > 0 + function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { + return kittyIndexToOwner[_tokenId] == _claimant; + } + + /// @dev Checks if a given address currently has transferApproval for a particular Kitty. + /// @param _claimant the address we are confirming kitten is approved for. + /// @param _tokenId kitten id, only valid when > 0 + function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) { + return kittyIndexToApproved[_tokenId] == _claimant; + } + + /// @dev Marks an address as being approved for transferFrom(), overwriting any previous + /// approval. Setting _approved to address(0) clears all transfer approval. + /// NOTE: _approve() does NOT send the Approval event. This is intentional because + /// _approve() and transferFrom() are used together for putting Kitties on auction, and + /// there is no value in spamming the log with Approval events in that case. + function _approve(uint256 _tokenId, address _approved) internal { + kittyIndexToApproved[_tokenId] = _approved; + } + + /// @notice Returns the number of Kitties owned by a specific address. + /// @param _owner The owner address to check. + /// @dev Required for ERC-721 compliance + function balanceOf(address _owner) public view returns (uint256 count) { + return ownershipTokenCount[_owner]; + } + + /// @notice Transfers a Kitty to another address. If transferring to a smart + /// contract be VERY CAREFUL to ensure that it is aware of ERC-721 (or + /// CryptoKitties specifically) or your Kitty may be lost forever. Seriously. + /// @param _to The address of the recipient, can be a user or contract. + /// @param _tokenId The ID of the Kitty to transfer. + /// @dev Required for ERC-721 compliance. + function transfer( + address _to, + uint256 _tokenId + ) + external + whenNotPaused + { + // Safety check to prevent against an unexpected 0x0 default. + require(_to != address(0)); + // Disallow transfers to this contract to prevent accidental misuse. + // The contract should never own any kitties (except very briefly + // after a gen0 cat is created and before it goes on auction). + require(_to != address(this)); + // Disallow transfers to the auction contracts to prevent accidental + // misuse. Auction contracts should only take ownership of kitties + // through the allow + transferFrom flow. + require(_to != address(saleAuction)); + require(_to != address(siringAuction)); + + // You can only send your own cat. + require(_owns(msg.sender, _tokenId)); + + // Reassign ownership, clear pending approvals, emit Transfer event. + _transfer(msg.sender, _to, _tokenId); + } + + /// @notice Grant another address the right to transfer a specific Kitty via + /// transferFrom(). This is the preferred flow for transfering NFTs to contracts. + /// @param _to The address to be granted transfer approval. Pass address(0) to + /// clear all approvals. + /// @param _tokenId The ID of the Kitty that can be transferred if this call succeeds. + /// @dev Required for ERC-721 compliance. + function approve( + address _to, + uint256 _tokenId + ) + external + whenNotPaused + { + // Only an owner can grant transfer approval. + require(_owns(msg.sender, _tokenId)); + + // Register the approval (replacing any previous approval). + _approve(_tokenId, _to); + + // Emit approval event. + emit Approval(msg.sender, _to, _tokenId); + } + + /// @notice Transfer a Kitty owned by another address, for which the calling address + /// has previously been granted transfer approval by the owner. + /// @param _from The address that owns the Kitty to be transfered. + /// @param _to The address that should take ownership of the Kitty. Can be any address, + /// including the caller. + /// @param _tokenId The ID of the Kitty to be transferred. + /// @dev Required for ERC-721 compliance. + function transferFrom( + address _from, + address _to, + uint256 _tokenId + ) + external + whenNotPaused + { + // Safety check to prevent against an unexpected 0x0 default. + require(_to != address(0)); + // Disallow transfers to this contract to prevent accidental misuse. + // The contract should never own any kitties (except very briefly + // after a gen0 cat is created and before it goes on auction). + require(_to != address(this)); + // Check for approval and valid ownership + require(_approvedFor(msg.sender, _tokenId)); + require(_owns(_from, _tokenId)); + + // Reassign ownership (also clears pending approvals and emits Transfer event). + _transfer(_from, _to, _tokenId); + } + + /// @notice Returns the total number of Kitties currently in existence. + /// @dev Required for ERC-721 compliance. + function totalSupply() public view returns (uint) { + return kitties.length - 1; + } + + /// @notice Returns the address currently assigned ownership of a given Kitty. + /// @dev Required for ERC-721 compliance. + function ownerOf(uint256 _tokenId) + external + view + returns (address owner) + { + owner = kittyIndexToOwner[_tokenId]; + + require(owner != address(0)); + } + + /// @notice Returns a list of all Kitty IDs assigned to an address. + /// @param _owner The owner whose Kitties we are interested in. + /// @dev This method MUST NEVER be called by smart contract code. First, it's fairly + /// expensive (it walks the entire Kitty array looking for cats belonging to owner), + /// but it also returns a dynamic array, which is only supported for web3 calls, and + /// not contract-to-contract calls. + function tokensOfOwner(address _owner) external view returns(uint256[] memory ownerTokens) { + uint256 tokenCount = balanceOf(_owner); + + if (tokenCount == 0) { + // Return an empty array + return new uint256[](0); + } else { + uint256[] memory result = new uint256[](tokenCount); + uint256 totalCats = totalSupply(); + uint256 resultIndex = 0; + + // We count on the fact that all cats have IDs starting at 1 and increasing + // sequentially up to the totalCat count. + uint256 catId; + + for (catId = 1; catId <= totalCats; catId++) { + if (kittyIndexToOwner[catId] == _owner) { + result[resultIndex] = catId; + resultIndex++; + } + } + + return result; + } + } + + /// @dev Adapted from memcpy() by @arachnid (Nick Johnson ) + /// This method is licenced under the Apache License. + /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol + function _memcpy(uint _dest, uint _src, uint _len) private view { + // Copy word-length chunks while possible + for(; _len >= 32; _len -= 32) { + assembly { + mstore(_dest, mload(_src)) + } + _dest += 32; + _src += 32; + } + + // Copy remaining bytes + uint256 mask = 256 ** (32 - _len) - 1; + assembly { + let srcpart := and(mload(_src), not(mask)) + let destpart := and(mload(_dest), mask) + mstore(_dest, or(destpart, srcpart)) + } + } + + /// @dev Adapted from toString(slice) by @arachnid (Nick Johnson ) + /// This method is licenced under the Apache License. + /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol + function _toString(bytes32[4] memory _rawBytes, uint256 _stringLength) private view returns (string memory) { + string memory outputString = new string(_stringLength); + uint256 outputPtr; + uint256 bytesPtr; + + assembly { + outputPtr := add(outputString, 32) + bytesPtr := _rawBytes + } + + _memcpy(outputPtr, bytesPtr, _stringLength); + + return outputString; + } + + /// @notice Returns a URI pointing to a metadata package for this token conforming to + /// ERC-721 (https://github.com/ethereum/EIPs/issues/721) + /// @param _tokenId The ID number of the Kitty whose metadata should be returned. + function tokenMetadata(uint256 _tokenId, string calldata _preferredTransport) external view returns (string memory infoUrl) { + require( address(erc721Metadata) != address(0)); + bytes32[4] memory buffer; + uint256 count; + (buffer, count) = erc721Metadata.getMetadata(_tokenId, _preferredTransport); + + return _toString(buffer, count); + } +} + + + + +/// @title A facet of KittyCore that manages Kitty siring, gestation, and birth. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. +contract KittyBreeding is KittyOwnership { + + /// @dev The Pregnant event is fired when two cats successfully breed and the pregnancy + /// timer begins for the matron. + event Pregnant(address owner, uint256 matronId, uint256 sireId, uint256 cooldownEndBlock); + + /// @notice The minimum payment required to use breedWithAuto(). This fee goes towards + /// the gas cost paid by whatever calls giveBirth(), and can be dynamically updated by + /// the COO role as the gas price changes. + uint256 public autoBirthFee = 2 finney; + + // Keeps track of number of pregnant kitties. + uint256 public pregnantKitties; + + /// @dev The address of the sibling contract that is used to implement the sooper-sekret + /// genetic combination algorithm. + GeneScienceInterface public geneScience; + + /// @dev Update the address of the genetic contract, can only be called by the CEO. + /// @param _address An address of a GeneScience contract instance to be used from this point forward. + function setGeneScienceAddress(address _address) external onlyCEO { + GeneScienceInterface candidateContract = GeneScienceInterface(_address); + + // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 + require(candidateContract.isGeneScience()); + + // Set the new contract address + geneScience = candidateContract; + } + + /// @dev Checks that a given kitten is able to breed. Requires that the + /// current cooldown is finished (for sires) and also checks that there is + /// no pending pregnancy. + function _isReadyToBreed(Kitty memory _kit) internal view returns (bool) { + // In addition to checking the cooldownEndBlock, we also need to check to see if + // the cat has a pending birth; there can be some period of time between the end + // of the pregnacy timer and the birth event. + return (_kit.siringWithId == 0) && (_kit.cooldownEndBlock <= uint64(block.number)); + } + + /// @dev Check if a sire has authorized breeding with this matron. True if both sire + /// and matron have the same owner, or if the sire has given siring permission to + /// the matron's owner (via approveSiring()). + function _isSiringPermitted(uint256 _sireId, uint256 _matronId) internal view returns (bool) { + address matronOwner = kittyIndexToOwner[_matronId]; + address sireOwner = kittyIndexToOwner[_sireId]; + + // Siring is okay if they have same owner, or if the matron's owner was given + // permission to breed with this sire. + return (matronOwner == sireOwner || sireAllowedToAddress[_sireId] == matronOwner); + } + + /// @dev Set the cooldownEndTime for the given Kitty, based on its current cooldownIndex. + /// Also increments the cooldownIndex (unless it has hit the cap). + /// @param _kitten A reference to the Kitty in storage which needs its timer started. + function _triggerCooldown(Kitty storage _kitten) internal { + // Compute an estimation of the cooldown time in blocks (based on current cooldownIndex). + _kitten.cooldownEndBlock = uint64((cooldowns[_kitten.cooldownIndex]/secondsPerBlock) + block.number); + + // Increment the breeding count, clamping it at 13, which is the length of the + // cooldowns array. We could check the array size dynamically, but hard-coding + // this as a constant saves gas. Yay, Solidity! + if (_kitten.cooldownIndex < 13) { + _kitten.cooldownIndex += 1; + } + } + + /// @notice Grants approval to another user to sire with one of your Kitties. + /// @param _addr The address that will be able to sire with your Kitty. Set to + /// address(0) to clear all siring approvals for this Kitty. + /// @param _sireId A Kitty that you own that _addr will now be able to sire with. + function approveSiring(address _addr, uint256 _sireId) + external + whenNotPaused + { + require(_owns(msg.sender, _sireId)); + sireAllowedToAddress[_sireId] = _addr; + } + + /// @dev Updates the minimum payment required for calling giveBirthAuto(). Can only + /// be called by the COO address. (This fee is used to offset the gas cost incurred + /// by the autobirth daemon). + function setAutoBirthFee(uint256 val) external onlyCOO { + autoBirthFee = val; + } + + /// @dev Checks to see if a given Kitty is pregnant and (if so) if the gestation + /// period has passed. + function _isReadyToGiveBirth(Kitty memory _matron) private view returns (bool) { + return (_matron.siringWithId != 0) && (_matron.cooldownEndBlock <= uint64(block.number)); + } + + /// @notice Checks that a given kitten is able to breed (i.e. it is not pregnant or + /// in the middle of a siring cooldown). + /// @param _kittyId reference the id of the kitten, any user can inquire about it + function isReadyToBreed(uint256 _kittyId) + public + view + returns (bool) + { + require(_kittyId > 0); + Kitty storage kit = kitties[_kittyId]; + return _isReadyToBreed(kit); + } + + /// @dev Checks whether a kitty is currently pregnant. + /// @param _kittyId reference the id of the kitten, any user can inquire about it + function isPregnant(uint256 _kittyId) + public + view + returns (bool) + { + require(_kittyId > 0); + // A kitty is pregnant if and only if this field is set + return kitties[_kittyId].siringWithId != 0; + } + + /// @dev Internal check to see if a given sire and matron are a valid mating pair. DOES NOT + /// check ownership permissions (that is up to the caller). + /// @param _matron A reference to the Kitty struct of the potential matron. + /// @param _matronId The matron's ID. + /// @param _sire A reference to the Kitty struct of the potential sire. + /// @param _sireId The sire's ID + function _isValidMatingPair( + Kitty storage _matron, + uint256 _matronId, + Kitty storage _sire, + uint256 _sireId + ) + private + view + returns(bool) + { + // A Kitty can't breed with itself! + if (_matronId == _sireId) { + return false; + } + + // Kitties can't breed with their parents. + if (_matron.matronId == _sireId || _matron.sireId == _sireId) { + return false; + } + if (_sire.matronId == _matronId || _sire.sireId == _matronId) { + return false; + } + + // We can short circuit the sibling check (below) if either cat is + // gen zero (has a matron ID of zero). + if (_sire.matronId == 0 || _matron.matronId == 0) { + return true; + } + + // Kitties can't breed with full or half siblings. + if (_sire.matronId == _matron.matronId || _sire.matronId == _matron.sireId) { + return false; + } + if (_sire.sireId == _matron.matronId || _sire.sireId == _matron.sireId) { + return false; + } + + // Everything seems cool! Let's get DTF. + return true; + } + + /// @dev Internal check to see if a given sire and matron are a valid mating pair for + /// breeding via auction (i.e. skips ownership and siring approval checks). + function _canBreedWithViaAuction(uint256 _matronId, uint256 _sireId) + internal + view + returns (bool) + { + Kitty storage matron = kitties[_matronId]; + Kitty storage sire = kitties[_sireId]; + return _isValidMatingPair(matron, _matronId, sire, _sireId); + } + + /// @notice Checks to see if two cats can breed together, including checks for + /// ownership and siring approvals. Does NOT check that both cats are ready for + /// breeding (i.e. breedWith could still fail until the cooldowns are finished). + /// TODO: Shouldn't this check pregnancy and cooldowns?!? + /// @param _matronId The ID of the proposed matron. + /// @param _sireId The ID of the proposed sire. + function canBreedWith(uint256 _matronId, uint256 _sireId) + external + view + returns(bool) + { + require(_matronId > 0); + require(_sireId > 0); + Kitty storage matron = kitties[_matronId]; + Kitty storage sire = kitties[_sireId]; + return _isValidMatingPair(matron, _matronId, sire, _sireId) && + _isSiringPermitted(_sireId, _matronId); + } + + /// @dev Internal utility function to initiate breeding, assumes that all breeding + /// requirements have been checked. + function _breedWith(uint256 _matronId, uint256 _sireId) internal { + // Grab a reference to the Kitties from storage. + Kitty storage sire = kitties[_sireId]; + Kitty storage matron = kitties[_matronId]; + + // Mark the matron as pregnant, keeping track of who the sire is. + matron.siringWithId = uint32(_sireId); + + // Trigger the cooldown for both parents. + _triggerCooldown(sire); + _triggerCooldown(matron); + + // Clear siring permission for both parents. This may not be strictly necessary + // but it's likely to avoid confusion! + delete sireAllowedToAddress[_matronId]; + delete sireAllowedToAddress[_sireId]; + + // Every time a kitty gets pregnant, counter is incremented. + pregnantKitties++; + + // Emit the pregnancy event. + emit Pregnant(kittyIndexToOwner[_matronId], _matronId, _sireId, matron.cooldownEndBlock); + } + + /// @notice Breed a Kitty you own (as matron) with a sire that you own, or for which you + /// have previously been given Siring approval. Will either make your cat pregnant, or will + /// fail entirely. Requires a pre-payment of the fee given out to the first caller of giveBirth() + /// @param _matronId The ID of the Kitty acting as matron (will end up pregnant if successful) + /// @param _sireId The ID of the Kitty acting as sire (will begin its siring cooldown if successful) + function breedWithAuto(uint256 _matronId, uint256 _sireId) + external + payable + whenNotPaused + { + // Checks for payment. + require(msg.value >= autoBirthFee); + + // Caller must own the matron. + require(_owns(msg.sender, _matronId)); + + // Neither sire nor matron are allowed to be on auction during a normal + // breeding operation, but we don't need to check that explicitly. + // For matron: The caller of this function can't be the owner of the matron + // because the owner of a Kitty on auction is the auction house, and the + // auction house will never call breedWith(). + // For sire: Similarly, a sire on auction will be owned by the auction house + // and the act of transferring ownership will have cleared any oustanding + // siring approval. + // Thus we don't need to spend gas explicitly checking to see if either cat + // is on auction. + + // Check that matron and sire are both owned by caller, or that the sire + // has given siring permission to caller (i.e. matron's owner). + // Will fail for _sireId = 0 + require(_isSiringPermitted(_sireId, _matronId)); + + // Grab a reference to the potential matron + Kitty storage matron = kitties[_matronId]; + + // Make sure matron isn't pregnant, or in the middle of a siring cooldown + require(_isReadyToBreed(matron)); + + // Grab a reference to the potential sire + Kitty storage sire = kitties[_sireId]; + + // Make sure sire isn't pregnant, or in the middle of a siring cooldown + require(_isReadyToBreed(sire)); + + // Test that these cats are a valid mating pair. + require(_isValidMatingPair( + matron, + _matronId, + sire, + _sireId + )); + + // All checks passed, kitty gets pregnant! + _breedWith(_matronId, _sireId); + } + + /// @notice Have a pregnant Kitty give birth! + /// @param _matronId A Kitty ready to give birth. + /// @return The Kitty ID of the new kitten. + /// @dev Looks at a given Kitty and, if pregnant and if the gestation period has passed, + /// combines the genes of the two parents to create a new kitten. The new Kitty is assigned + /// to the current owner of the matron. Upon successful completion, both the matron and the + /// new kitten will be ready to breed again. Note that anyone can call this function (if they + /// are willing to pay the gas!), but the new kitten always goes to the mother's owner. + function giveBirth(uint256 _matronId) + external + whenNotPaused + returns(uint256) + { + // Grab a reference to the matron in storage. + Kitty storage matron = kitties[_matronId]; + + // Check that the matron is a valid cat. + require(matron.birthTime != 0); + + // Check that the matron is pregnant, and that its time has come! + require(_isReadyToGiveBirth(matron)); + + // Grab a reference to the sire in storage. + uint256 sireId = matron.siringWithId; + Kitty storage sire = kitties[sireId]; + + // Determine the higher generation number of the two parents + uint16 parentGen = matron.generation; + if (sire.generation > matron.generation) { + parentGen = sire.generation; + } + + // Call the sooper-sekret gene mixing operation. + uint256 childGenes = geneScience.mixGenes(matron.genes, sire.genes, matron.cooldownEndBlock - 1); + + // Make the new kitten! + address owner = kittyIndexToOwner[_matronId]; + uint256 kittenId = _createKitty(_matronId, matron.siringWithId, parentGen + 1, childGenes, owner); + + // Clear the reference to sire from the matron (REQUIRED! Having siringWithId + // set is what marks a matron as being pregnant.) + delete matron.siringWithId; + + // Every time a kitty gives birth counter is decremented. + pregnantKitties--; + + // Send the balance fee to the person who made birth happen. + msg.sender.transfer(autoBirthFee); + + // return the new kitten's ID + return kittenId; + } +} + + + +/// @title Handles creating auctions for sale and siring of kitties. +/// This wrapper of ReverseAuction exists only so that users can create +/// auctions with only one transaction. +contract KittyAuction is KittyBreeding { + + // @notice The auction contract variables are defined in KittyBase to allow + // us to refer to them in KittyOwnership to prevent accidental transfers. + // `saleAuction` refers to the auction for gen0 and p2p sale of kitties. + // `siringAuction` refers to the auction for siring rights of kitties. + + /// @dev Sets the reference to the sale auction. + /// @param _address - Address of sale contract. + function setSaleAuctionAddress(address _address) external onlyCEO { + SaleClockAuction candidateContract = SaleClockAuction(_address); + + // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 + require(candidateContract.isSaleClockAuction()); + + // Set the new contract address + saleAuction = candidateContract; + } + + /// @dev Sets the reference to the siring auction. + /// @param _address - Address of siring contract. + function setSiringAuctionAddress(address _address) external onlyCEO { + SiringClockAuction candidateContract = SiringClockAuction(_address); + + // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 + require(candidateContract.isSiringClockAuction()); + + // Set the new contract address + siringAuction = candidateContract; + } + + /// @dev Put a kitty up for auction. + /// Does some ownership trickery to create auctions in one tx. + function createSaleAuction( + uint256 _kittyId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration + ) + external + whenNotPaused + { + // Auction contract checks input sizes + // If kitty is already on any auction, this will throw + // because it will be owned by the auction contract. + require(_owns(msg.sender, _kittyId)); + // Ensure the kitty is not pregnant to prevent the auction + // contract accidentally receiving ownership of the child. + // NOTE: the kitty IS allowed to be in a cooldown. + require(!isPregnant(_kittyId)); + _approve(_kittyId, address(saleAuction)); + // Sale auction throws if inputs are invalid and clears + // transfer and sire approval after escrowing the kitty. + saleAuction.createAuction( + _kittyId, + _startingPrice, + _endingPrice, + _duration, + msg.sender + ); + } + + /// @dev Put a kitty up for auction to be sire. + /// Performs checks to ensure the kitty can be sired, then + /// delegates to reverse auction. + function createSiringAuction( + uint256 _kittyId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration + ) + external + whenNotPaused + { + // Auction contract checks input sizes + // If kitty is already on any auction, this will throw + // because it will be owned by the auction contract. + require(_owns(msg.sender, _kittyId)); + require(isReadyToBreed(_kittyId)); + _approve(_kittyId, address(siringAuction)); + // Siring auction throws if inputs are invalid and clears + // transfer and sire approval after escrowing the kitty. + siringAuction.createAuction( + _kittyId, + _startingPrice, + _endingPrice, + _duration, + msg.sender + ); + } + + /// @dev Completes a siring auction by bidding. + /// Immediately breeds the winning matron with the sire on auction. + /// @param _sireId - ID of the sire on auction. + /// @param _matronId - ID of the matron owned by the bidder. + function bidOnSiringAuction( + uint256 _sireId, + uint256 _matronId + ) + external + payable + whenNotPaused + { + // Auction contract checks input sizes + require(_owns(msg.sender, _matronId)); + require(isReadyToBreed(_matronId)); + require(_canBreedWithViaAuction(_matronId, _sireId)); + + // Define the current price of the auction. + uint256 currentPrice = siringAuction.getCurrentPrice(_sireId); + require(msg.value >= currentPrice + autoBirthFee); + + // Siring auction will throw if the bid fails. + siringAuction.bid.value(msg.value - autoBirthFee)(_sireId); + _breedWith(uint32(_matronId), uint32(_sireId)); + } + + /// @dev Transfers the balance of the sale auction contract + /// to the KittyCore contract. We use two-step withdrawal to + /// prevent two transfer calls in the auction bid function. + function withdrawAuctionBalances() external onlyCLevel { + saleAuction.withdrawBalance(); + siringAuction.withdrawBalance(); + } +} + + +/// @title all functions related to creating kittens +contract KittyMinting is KittyAuction { + + // Limits the number of cats the contract owner can ever create. + uint256 public constant PROMO_CREATION_LIMIT = 5000; + uint256 public constant GEN0_CREATION_LIMIT = 45000; + + // Constants for gen0 auctions. + uint256 public constant GEN0_STARTING_PRICE = 10 finney; + uint256 public constant GEN0_AUCTION_DURATION = 1 days; + + // Counts the number of cats the contract owner has created. + uint256 public promoCreatedCount; + uint256 public gen0CreatedCount; + + /// @dev we can create promo kittens, up to a limit. Only callable by COO + /// @param _genes the encoded genes of the kitten to be created, any value is accepted + /// @param _owner the future owner of the created kittens. Default to contract COO + function createPromoKitty(uint256 _genes, address _owner) external onlyCOO { + address kittyOwner = _owner; + if (kittyOwner == address(0)) { + kittyOwner = cooAddress; + } + require(promoCreatedCount < PROMO_CREATION_LIMIT); + + promoCreatedCount++; + _createKitty(0, 0, 0, _genes, kittyOwner); + } + + /// @dev Creates a new gen0 kitty with the given genes and + /// creates an auction for it. + function createGen0Auction(uint256 _genes) external onlyCOO { + require(gen0CreatedCount < GEN0_CREATION_LIMIT); + + uint256 kittyId = _createKitty(0, 0, 0, _genes, address(this)); + _approve(kittyId, address(saleAuction)); + + saleAuction.createAuction( + kittyId, + _computeNextGen0Price(), + 0, + GEN0_AUCTION_DURATION, + address(uint160(address(this))) + ); + + gen0CreatedCount++; + } + + /// @dev Computes the next gen0 auction starting price, given + /// the average of the past 5 prices + 50%. + function _computeNextGen0Price() internal view returns (uint256) { + uint256 avePrice = saleAuction.averageGen0SalePrice(); + + // Sanity check to ensure we don't overflow arithmetic + require(avePrice == uint256(uint128(avePrice))); + + uint256 nextPrice = avePrice + (avePrice / 2); + + // We never auction for less than starting price + if (nextPrice < GEN0_STARTING_PRICE) { + nextPrice = GEN0_STARTING_PRICE; + } + + return nextPrice; + } +} + + + +/// @title CryptoKitties: Collectible, breedable, and oh-so-adorable cats on the Ethereum blockchain. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev The main CryptoKitties contract, keeps track of kittens so they don't wander around and get lost. +contract KittyCore is KittyMinting { + + // This is the main CryptoKitties contract. In order to keep our code seperated into logical sections, + // we've broken it up in two ways. First, we have several seperately-instantiated sibling contracts + // that handle auctions and our super-top-secret genetic combination algorithm. The auctions are + // seperate since their logic is somewhat complex and there's always a risk of subtle bugs. By keeping + // them in their own contracts, we can upgrade them without disrupting the main contract that tracks + // kitty ownership. The genetic combination algorithm is kept seperate so we can open-source all of + // the rest of our code without making it _too_ easy for folks to figure out how the genetics work. + // Don't worry, I'm sure someone will reverse engineer it soon enough! + // + // Secondly, we break the core contract into multiple files using inheritence, one for each major + // facet of functionality of CK. This allows us to keep related code bundled together while still + // avoiding a single giant file with everything in it. The breakdown is as follows: + // + // - KittyBase: This is where we define the most fundamental code shared throughout the core + // functionality. This includes our main data storage, constants and data types, plus + // internal functions for managing these items. + // + // - KittyAccessControl: This contract manages the various addresses and constraints for operations + // that can be executed only by specific roles. Namely CEO, CFO and COO. + // + // - KittyOwnership: This provides the methods required for basic non-fungible token + // transactions, following the draft ERC-721 spec (https://github.com/ethereum/EIPs/issues/721). + // + // - KittyBreeding: This file contains the methods necessary to breed cats together, including + // keeping track of siring offers, and relies on an external genetic combination contract. + // + // - KittyAuctions: Here we have the public methods for auctioning or bidding on cats or siring + // services. The actual auction functionality is handled in two sibling contracts (one + // for sales and one for siring), while auction creation and bidding is mostly mediated + // through this facet of the core contract. + // + // - KittyMinting: This final facet contains the functionality we use for creating new gen0 cats. + // We can make up to 5000 "promo" cats that can be given away (especially important when + // the community is new), and all others can only be created and then immediately put up + // for auction via an algorithmically determined starting price. Regardless of how they + // are created, there is a hard limit of 50k gen0 cats. After that, it's all up to the + // community to breed, breed, breed! + + // Set in case the core contract is broken and an upgrade is required + address public newContractAddress; + + /// @notice Creates the main CryptoKitties smart contract instance. + constructor() public { + // Starts paused. + paused = true; + + // the creator of the contract is the initial CEO + ceoAddress = msg.sender; + + // the creator of the contract is also the initial COO + cooAddress = msg.sender; + + // start with the mythical kitten 0 - so we don't have generation-0 parent issues + _createKitty(0, 0, 0, uint256(-1), address(0)); + } + + /// @dev Used to mark the smart contract as upgraded, in case there is a serious + /// breaking bug. This method does nothing but keep track of the new contract and + /// emit a message indicating that the new address is set. It's up to clients of this + /// contract to update to the new contract address in that case. (This contract will + /// be paused indefinitely if such an upgrade takes place.) + /// @param _v2Address new address + function setNewAddress(address _v2Address) external onlyCEO whenPaused { + // See README.md for updgrade plan + newContractAddress = _v2Address; + emit ContractUpgrade(_v2Address); + } + + /// @notice No tipping! + /// @dev Reject all Ether from being sent here, unless it's from one of the + /// two auction contracts. (Hopefully, we can prevent user accidents.) + function() external payable { + require( + msg.sender == address(saleAuction) || + msg.sender == address(siringAuction) + ); + } + + /// @notice Returns all the relevant information about a specific kitty. + /// @param _id The ID of the kitty of interest. + function getKitty(uint256 _id) + external + view + returns ( + bool isGestating, + bool isReady, + uint256 cooldownIndex, + uint256 nextActionAt, + uint256 siringWithId, + uint256 birthTime, + uint256 matronId, + uint256 sireId, + uint256 generation, + uint256 genes + ) { + Kitty storage kit = kitties[_id]; + + // if this variable is 0 then it's not gestating + isGestating = (kit.siringWithId != 0); + isReady = (kit.cooldownEndBlock <= block.number); + cooldownIndex = uint256(kit.cooldownIndex); + nextActionAt = uint256(kit.cooldownEndBlock); + siringWithId = uint256(kit.siringWithId); + birthTime = uint256(kit.birthTime); + matronId = uint256(kit.matronId); + sireId = uint256(kit.sireId); + generation = uint256(kit.generation); + genes = kit.genes; + } + + /// @dev Override unpause so it requires all external contract addresses + /// to be set before contract can be unpaused. Also, we can't have + /// newContractAddress set either, because then the contract was upgraded. + /// @notice This is public rather than external so we can call super.unpause + /// without using an expensive CALL. + + function unpause(address payable toAddress, uint256 tokenValue, trcToken tokenId) public onlyCEO whenPaused returns (uint256 r) { + require(address(saleAuction) != address(0)); + require(address(siringAuction) != address(0)); + require(address(geneScience) != address(0)); + require(address(newContractAddress) == address(0)); + toAddress.transferToken(tokenValue, tokenId); + r = address(this).tokenBalance(tokenId); + // Actually unpause the contract. + super.unpause(); + } + + // @dev Allows the CFO to capture the balance available to the contract. + function withdrawBalance() external onlyCFO { + uint256 balance = address(this).balance; + // Subtract all the currently pregnant kittens we have, plus 1 of margin. + uint256 subtractFees = (pregnantKitties + 1) * autoBirthFee; + + if (balance > subtractFees) { + cfoAddress.transfer(balance - subtractFees); + } + } +} + + + + + + + + + + + + + +// // Auction wrapper functions + + +// Auction wrapper functions + + + + + + + +/// @title SEKRETOOOO +contract GeneScienceInterface { + + function isGeneScience() public pure returns (bool){ + return true; + } + + /// @dev given genes of kitten 1 & 2, return a genetic combination - may have a random factor + /// @param genes1 genes of mom + /// @param genes2 genes of sire + /// @return the genes that are supposed to be passed down the child + function mixGenes(uint256 genes1, uint256 genes2, uint256 targetBlock) public pure returns (uint256){ + + return (genes1+genes2+targetBlock)/2; + + +} +} + + + + + + + + + + + + + + + + +/// @title The external contract that is responsible for generating metadata for the kitties, +/// it has one function that will return the data as bytes. +contract ERC721Metadata { + /// @dev Given a token Id, returns a byte array that is supposed to be converted into string. + function getMetadata(uint256 _tokenId, string memory) public view returns (bytes32[4] memory buffer, uint256 count) { + if (_tokenId == 1) { + buffer[0] = "Hello World! :D"; + count = 15; + } else if (_tokenId == 2) { + buffer[0] = "I would definitely choose a medi"; + buffer[1] = "um length string."; + count = 49; + } else if (_tokenId == 3) { + buffer[0] = "Lorem ipsum dolor sit amet, mi e"; + buffer[1] = "st accumsan dapibus augue lorem,"; + buffer[2] = " tristique vestibulum id, libero"; + buffer[3] = " suscipit varius sapien aliquam."; + count = 128; + } + } +} + + + + + + + + + + + + + + + +/// @title Auction Core +/// @dev Contains models, variables, and internal methods for the auction. +/// @notice We omit a fallback function to prevent accidental sends to this contract. +contract ClockAuctionBase { + + // Represents an auction on an NFT + struct Auction { + // Current owner of NFT + address payable seller; + // Price (in wei) at beginning of auction + uint128 startingPrice; + // Price (in wei) at end of auction + uint128 endingPrice; + // Duration (in seconds) of auction + uint64 duration; + // Time when auction started + // NOTE: 0 if this auction has been concluded + uint64 startedAt; + } + + // Reference to contract tracking NFT ownership + ERC721 public nonFungibleContract; + + // Cut owner takes on each auction, measured in basis points (1/100 of a percent). + // Values 0-10,000 map to 0%-100% + uint256 public ownerCut; + + // Map from token ID to their corresponding auction. + mapping (uint256 => Auction) tokenIdToAuction; + + event AuctionCreated(uint256 tokenId, uint256 startingPrice, uint256 endingPrice, uint256 duration); + event AuctionSuccessful(uint256 tokenId, uint256 totalPrice, address winner); + event AuctionCancelled(uint256 tokenId); + + /// @dev Returns true if the claimant owns the token. + /// @param _claimant - Address claiming to own the token. + /// @param _tokenId - ID of token whose ownership to verify. + function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { + return (nonFungibleContract.ownerOf(_tokenId) == _claimant); + } + + /// @dev Escrows the NFT, assigning ownership to this contract. + /// Throws if the escrow fails. + /// @param _owner - Current owner address of token to escrow. + /// @param _tokenId - ID of token whose approval to verify. + function _escrow(address _owner, uint256 _tokenId) internal { + // it will throw if transfer fails + nonFungibleContract.transferFrom(_owner, address(this), _tokenId); + } + + /// @dev Transfers an NFT owned by this contract to another address. + /// Returns true if the transfer succeeds. + /// @param _receiver - Address to transfer NFT to. + /// @param _tokenId - ID of token to transfer. + function _transfer(address _receiver, uint256 _tokenId) internal { + // it will throw if transfer fails + nonFungibleContract.transfer(_receiver, _tokenId); + } + + /// @dev Adds an auction to the list of open auctions. Also fires the + /// AuctionCreated event. + /// @param _tokenId The ID of the token to be put on auction. + /// @param _auction Auction to add. + function _addAuction(uint256 _tokenId, Auction memory _auction) internal { + // Require that all auctions have a duration of + // at least one minute. (Keeps our math from getting hairy!) + require(_auction.duration >= 1 minutes); + + tokenIdToAuction[_tokenId] = _auction; + + emit AuctionCreated( + uint256(_tokenId), + uint256(_auction.startingPrice), + uint256(_auction.endingPrice), + uint256(_auction.duration) + ); + } + + /// @dev Cancels an auction unconditionally. + function _cancelAuction(uint256 _tokenId, address _seller) internal { + _removeAuction(_tokenId); + _transfer(_seller, _tokenId); + emit AuctionCancelled(_tokenId); + } + + /// @dev Computes the price and transfers winnings. + /// Does NOT transfer ownership of token. + function _bid(uint256 _tokenId, uint256 _bidAmount) + internal + returns (uint256) + { + // Get a reference to the auction struct + Auction storage auction = tokenIdToAuction[_tokenId]; + + // Explicitly check that this auction is currently live. + // (Because of how Ethereum mappings work, we can't just count + // on the lookup above failing. An invalid _tokenId will just + // return an auction object that is all zeros.) + require(_isOnAuction(auction)); + + // Check that the bid is greater than or equal to the current price + uint256 price = _currentPrice(auction); + require(_bidAmount >= price); + + // Grab a reference to the seller before the auction struct + // gets deleted. + address payable seller = auction.seller; + + // The bid is good! Remove the auction before sending the fees + // to the sender so we can't have a reentrancy attack. + _removeAuction(_tokenId); + + // Transfer proceeds to seller (if there are any!) + if (price > 0) { + // Calculate the auctioneer's cut. + // (NOTE: _computeCut() is guaranteed to return a + // value <= price, so this subtraction can't go negative.) + uint256 auctioneerCut = _computeCut(price); + uint256 sellerProceeds = price - auctioneerCut; + + // NOTE: Doing a transfer() in the middle of a complex + // method like this is generally discouraged because of + // reentrancy attacks and DoS attacks if the seller is + // a contract with an invalid fallback function. We explicitly + // guard against reentrancy attacks by removing the auction + // before calling transfer(), and the only thing the seller + // can DoS is the sale of their own asset! (And if it's an + // accident, they can call cancelAuction(). ) + seller.transfer(sellerProceeds); + } + + // Calculate any excess funds included with the bid. If the excess + // is anything worth worrying about, transfer it back to bidder. + // NOTE: We checked above that the bid amount is greater than or + // equal to the price so this cannot underflow. + uint256 bidExcess = _bidAmount - price; + + // Return the funds. Similar to the previous transfer, this is + // not susceptible to a re-entry attack because the auction is + // removed before any transfers occur. + msg.sender.transfer(bidExcess); + + // Tell the world! + emit AuctionSuccessful(_tokenId, price, msg.sender); + + return price; + } + + /// @dev Removes an auction from the list of open auctions. + /// @param _tokenId - ID of NFT on auction. + function _removeAuction(uint256 _tokenId) internal { + delete tokenIdToAuction[_tokenId]; + } + + /// @dev Returns true if the NFT is on auction. + /// @param _auction - Auction to check. + function _isOnAuction(Auction storage _auction) internal view returns (bool) { + return (_auction.startedAt > 0); + } + + /// @dev Returns current price of an NFT on auction. Broken into two + /// functions (this one, that computes the duration from the auction + /// structure, and the other that does the price computation) so we + /// can easily test that the price computation works correctly. + function _currentPrice(Auction storage _auction) + internal + view + returns (uint256) + { + uint256 secondsPassed = 0; + + // A bit of insurance against negative values (or wraparound). + // Probably not necessary (since Ethereum guarnatees that the + // now variable doesn't ever go backwards). + if (now > _auction.startedAt) { + secondsPassed = now - _auction.startedAt; + } + + return _computeCurrentPrice( + _auction.startingPrice, + _auction.endingPrice, + _auction.duration, + secondsPassed + ); + } + + /// @dev Computes the current price of an auction. Factored out + /// from _currentPrice so we can run extensive unit tests. + /// When testing, make this function public and turn on + /// `Current price computation` test suite. + function _computeCurrentPrice( + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration, + uint256 _secondsPassed + ) + internal + pure + returns (uint256) + { + // NOTE: We don't use SafeMath (or similar) in this function because + // all of our public functions carefully cap the maximum values for + // time (at 64-bits) and currency (at 128-bits). _duration is + // also known to be non-zero (see the require() statement in + // _addAuction()) + if (_secondsPassed >= _duration) { + // We've reached the end of the dynamic pricing portion + // of the auction, just return the end price. + return _endingPrice; + } else { + // Starting price can be higher than ending price (and often is!), so + // this delta can be negative. + int256 totalPriceChange = int256(_endingPrice) - int256(_startingPrice); + + // This multiplication can't overflow, _secondsPassed will easily fit within + // 64-bits, and totalPriceChange will easily fit within 128-bits, their product + // will always fit within 256-bits. + int256 currentPriceChange = totalPriceChange * int256(_secondsPassed) / int256(_duration); + + // currentPriceChange can be negative, but if so, will have a magnitude + // less that _startingPrice. Thus, this result will always end up positive. + int256 currentPrice = int256(_startingPrice) + currentPriceChange; + + return uint256(currentPrice); + } + } + + /// @dev Computes owner's cut of a sale. + /// @param _price - Sale price of NFT. + function _computeCut(uint256 _price) internal view returns (uint256) { + // NOTE: We don't use SafeMath (or similar) in this function because + // all of our entry functions carefully cap the maximum values for + // currency (at 128-bits), and ownerCut <= 10000 (see the require() + // statement in the ClockAuction constructor). The result of this + // function is always guaranteed to be <= _price. + return _price * ownerCut / 10000; + } + +} + + + + + + + +/** + * @title Pausable + * @dev Base contract which allows children to implement an emergency stop mechanism. + */ +contract Pausable is Ownable { + event Pause(); + event Unpause(); + + bool public paused = false; + + + /** + * @dev modifier to allow actions only when the contract IS paused + */ + modifier whenNotPaused() { + require(!paused); + _; + } + + /** + * @dev modifier to allow actions only when the contract IS NOT paused + */ + modifier whenPaused { + require(paused); + _; + } + + /** + * @dev called by the owner to pause, triggers stopped state + */ + function pause() onlyOwner whenNotPaused public returns (bool) { + paused = true; + emit Pause(); + return true; + } + + /** + * @dev called by the owner to unpause, returns to normal state + */ + function unpause() onlyOwner whenPaused public returns (bool) { + paused = false; + emit Unpause(); + return true; + } +} + + +/// @title Clock auction for non-fungible tokens. +/// @notice We omit a fallback function to prevent accidental sends to this contract. +contract ClockAuction is Pausable, ClockAuctionBase { + + /// @dev The ERC-165 interface signature for ERC-721. + /// Ref: https://github.com/ethereum/EIPs/issues/165 + /// Ref: https://github.com/ethereum/EIPs/issues/721 + bytes4 constant InterfaceSignature_ERC721 = bytes4(0x9a20483d); + + /// @dev Constructor creates a reference to the NFT ownership contract + /// and verifies the owner cut is in the valid range. + /// @param _nftAddress - address of a deployed contract implementing + /// the Nonfungible Interface. + /// @param _cut - percent cut the owner takes on each auction, must be + /// between 0-10,000. + constructor(address _nftAddress, uint256 _cut) public { + require(_cut <= 10000); + ownerCut = _cut; + + ERC721 candidateContract = ERC721(_nftAddress); + require(candidateContract.supportsInterface(InterfaceSignature_ERC721)); + nonFungibleContract = candidateContract; + } + + /// @dev Remove all Ether from the contract, which is the owner's cuts + /// as well as any Ether sent directly to the contract address. + /// Always transfers to the NFT contract, but can be called either by + /// the owner or the NFT contract. + function withdrawBalance() external { + address payable nftAddress = address(uint160(address(nonFungibleContract))); + + require( + msg.sender == owner || + msg.sender == nftAddress + ); + // We are using this boolean method to make sure that even if one fails it will still work + bool res = nftAddress.send(address(this).balance); + } + + /// @dev Creates and begins a new auction. + /// @param _tokenId - ID of token to auction, sender must be owner. + /// @param _startingPrice - Price of item (in wei) at beginning of auction. + /// @param _endingPrice - Price of item (in wei) at end of auction. + /// @param _duration - Length of time to move between starting + /// price and ending price (in seconds). + /// @param _seller - Seller, if not the message sender + function createAuction( + uint256 _tokenId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration, + address payable _seller + ) + external + whenNotPaused + { + // Sanity check that no inputs overflow how many bits we've allocated + // to store them in the auction struct. + require(_startingPrice == uint256(uint128(_startingPrice))); + require(_endingPrice == uint256(uint128(_endingPrice))); + require(_duration == uint256(uint64(_duration))); + + require(_owns(msg.sender, _tokenId)); + _escrow(msg.sender, _tokenId); + Auction memory auction = Auction( + _seller, + uint128(_startingPrice), + uint128(_endingPrice), + uint64(_duration), + uint64(now) + ); + _addAuction(_tokenId, auction); + } + + /// @dev Bids on an open auction, completing the auction and transferring + /// ownership of the NFT if enough Ether is supplied. + /// @param _tokenId - ID of token to bid on. + function bid(uint256 _tokenId) + external + payable + whenNotPaused + { + // _bid will throw if the bid or funds transfer fails + _bid(_tokenId, msg.value); + _transfer(msg.sender, _tokenId); + } + + /// @dev Cancels an auction that hasn't been won yet. + /// Returns the NFT to original owner. + /// @notice This is a state-modifying function that can + /// be called while the contract is paused. + /// @param _tokenId - ID of token on auction + function cancelAuction(uint256 _tokenId) + external + { + Auction storage auction = tokenIdToAuction[_tokenId]; + require(_isOnAuction(auction)); + address seller = auction.seller; + require(msg.sender == seller); + _cancelAuction(_tokenId, seller); + } + + /// @dev Cancels an auction when the contract is paused. + /// Only the owner may do this, and NFTs are returned to + /// the seller. This should only be used in emergencies. + /// @param _tokenId - ID of the NFT on auction to cancel. + function cancelAuctionWhenPaused(uint256 _tokenId) + whenPaused + onlyOwner + external + { + Auction storage auction = tokenIdToAuction[_tokenId]; + require(_isOnAuction(auction)); + _cancelAuction(_tokenId, auction.seller); + } + + /// @dev Returns auction info for an NFT on auction. + /// @param _tokenId - ID of NFT on auction. + function getAuction(uint256 _tokenId) + external + view + returns + ( + address seller, + uint256 startingPrice, + uint256 endingPrice, + uint256 duration, + uint256 startedAt + ) { + Auction storage auction = tokenIdToAuction[_tokenId]; + require(_isOnAuction(auction)); + return ( + auction.seller, + auction.startingPrice, + auction.endingPrice, + auction.duration, + auction.startedAt + ); + } + + /// @dev Returns the current price of an auction. + /// @param _tokenId - ID of the token price we are checking. + function getCurrentPrice(uint256 _tokenId) + external + view + returns (uint256) + { + Auction storage auction = tokenIdToAuction[_tokenId]; + require(_isOnAuction(auction)); + return _currentPrice(auction); + } + +} + + +/// @title Reverse auction modified for siring +/// @notice We omit a fallback function to prevent accidental sends to this contract. +contract SiringClockAuction is ClockAuction { + + // @dev Sanity check that allows us to ensure that we are pointing to the + // right auction in our setSiringAuctionAddress() call. + bool public isSiringClockAuction = true; + + // Delegate constructor + constructor(address _nftAddr, uint256 _cut) public + ClockAuction(_nftAddr, _cut) {} + + /// @dev Creates and begins a new auction. Since this function is wrapped, + /// require sender to be KittyCore contract. + /// @param _tokenId - ID of token to auction, sender must be owner. + /// @param _startingPrice - Price of item (in wei) at beginning of auction. + /// @param _endingPrice - Price of item (in wei) at end of auction. + /// @param _duration - Length of auction (in seconds). + /// @param _seller - Seller, if not the message sender + function createAuction( + uint256 _tokenId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration, + address payable _seller + ) + external + { + // Sanity check that no inputs overflow how many bits we've allocated + // to store them in the auction struct. + require(_startingPrice == uint256(uint128(_startingPrice))); + require(_endingPrice == uint256(uint128(_endingPrice))); + require(_duration == uint256(uint64(_duration))); + + require(msg.sender == address(nonFungibleContract)); + _escrow(_seller, _tokenId); + Auction memory auction = Auction( + _seller, + uint128(_startingPrice), + uint128(_endingPrice), + uint64(_duration), + uint64(now) + ); + _addAuction(_tokenId, auction); + } + + /// @dev Places a bid for siring. Requires the sender + /// is the KittyCore contract because all bid methods + /// should be wrapped. Also returns the kitty to the + /// seller rather than the winner. + function bid(uint256 _tokenId) + external + payable + { + require(msg.sender == address(nonFungibleContract)); + address seller = tokenIdToAuction[_tokenId].seller; + // _bid checks that token ID is valid and will throw if bid fails + _bid(_tokenId, msg.value); + // We transfer the kitty back to the seller, the winner will get + // the offspring + _transfer(seller, _tokenId); + } + +} + + + + + +/// @title Clock auction modified for sale of kitties +/// @notice We omit a fallback function to prevent accidental sends to this contract. +contract SaleClockAuction is ClockAuction { + + // @dev Sanity check that allows us to ensure that we are pointing to the + // right auction in our setSaleAuctionAddress() call. + bool public isSaleClockAuction = true; + + // Tracks last 5 sale price of gen0 kitty sales + uint256 public gen0SaleCount; + uint256[5] public lastGen0SalePrices; + + // Delegate constructor + constructor(address _nftAddr, uint256 _cut) public + ClockAuction(_nftAddr, _cut) {} + + /// @dev Creates and begins a new auction. + /// @param _tokenId - ID of token to auction, sender must be owner. + /// @param _startingPrice - Price of item (in wei) at beginning of auction. + /// @param _endingPrice - Price of item (in wei) at end of auction. + /// @param _duration - Length of auction (in seconds). + /// @param _seller - Seller, if not the message sender + function createAuction( + uint256 _tokenId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration, + address payable _seller + ) + external + { + // Sanity check that no inputs overflow how many bits we've allocated + // to store them in the auction struct. + require(_startingPrice == uint256(uint128(_startingPrice))); + require(_endingPrice == uint256(uint128(_endingPrice))); + require(_duration == uint256(uint64(_duration))); + + require(msg.sender == address(nonFungibleContract)); + _escrow(_seller, _tokenId); + Auction memory auction = Auction( + _seller, + uint128(_startingPrice), + uint128(_endingPrice), + uint64(_duration), + uint64(now) + ); + _addAuction(_tokenId, auction); + } + + /// @dev Updates lastSalePrice if seller is the nft contract + /// Otherwise, works the same as default bid method. + function bid(uint256 _tokenId) + external + payable + { + // _bid verifies token ID size + address seller = tokenIdToAuction[_tokenId].seller; + uint256 price = _bid(_tokenId, msg.value); + _transfer(msg.sender, _tokenId); + + // If not a gen0 auction, exit + if (seller == address(nonFungibleContract)) { + // Track gen0 sale prices + lastGen0SalePrices[gen0SaleCount % 5] = price; + gen0SaleCount++; + } + } + + function averageGen0SalePrice() external view returns (uint256) { + uint256 sum = 0; + for (uint256 i = 0; i < 5; i++) { + sum += lastGen0SalePrices[i]; + } + return sum / 5; + } + +} + + + + + + + diff --git a/src/test/resources/soliditycode/assertExceptiontest1DivideInt.sol b/src/test/resources/soliditycode/assertExceptiontest1DivideInt.sol new file mode 100644 index 00000000000..ca38896acee --- /dev/null +++ b/src/test/resources/soliditycode/assertExceptiontest1DivideInt.sol @@ -0,0 +1,7 @@ +//pragma solidity ^0.4.0; + +contract divideIHaveArgsReturnStorage{ +function divideIHaveArgsReturn(int x,int y) public returns (int z) { +return z = x / y; +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/assertExceptiontest2FindArgsContractMinTest.sol b/src/test/resources/soliditycode/assertExceptiontest2FindArgsContractMinTest.sol new file mode 100644 index 00000000000..b8565d2578e --- /dev/null +++ b/src/test/resources/soliditycode/assertExceptiontest2FindArgsContractMinTest.sol @@ -0,0 +1,10 @@ +//pragma solidity ^0.4.0; +contract findArgsIContract{ +function findArgsByIndex1(uint i) public returns (uint z) { +uint[] memory a = new uint[](3); +a[0]=1; +a[1]=2; +a[2]=3; +return a[i]; +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/assertExceptiontest3ByteMinContract.sol b/src/test/resources/soliditycode/assertExceptiontest3ByteMinContract.sol new file mode 100644 index 00000000000..6d846fad7f4 --- /dev/null +++ b/src/test/resources/soliditycode/assertExceptiontest3ByteMinContract.sol @@ -0,0 +1,11 @@ +pragma solidity >0.5.0; +contract byteContract{ +bytes b; +function testBytesGet(uint i) public returns (bytes1){ +b = new bytes(3); +b[0]=0x0b; +b[1]=0x0c; +b[2]=0x0d; +return b[i]; +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/assertExceptiontest4Enum.sol b/src/test/resources/soliditycode/assertExceptiontest4Enum.sol new file mode 100644 index 00000000000..4a740d4a089 --- /dev/null +++ b/src/test/resources/soliditycode/assertExceptiontest4Enum.sol @@ -0,0 +1,13 @@ +//pragma solidity ^0.4.4; + +contract enumContract { + enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill } + ActionChoices _choice; + function setGoStraight(ActionChoices choice) public { + _choice = choice; + } + + function getChoice() public returns (ActionChoices) { + return _choice; + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/assertExceptiontest5MoveRight.sol b/src/test/resources/soliditycode/assertExceptiontest5MoveRight.sol new file mode 100644 index 00000000000..7194520fb09 --- /dev/null +++ b/src/test/resources/soliditycode/assertExceptiontest5MoveRight.sol @@ -0,0 +1,7 @@ +//pragma solidity ^0.4.0; + +contract binaryRightContract{ + function binaryMoveR(int i)public returns (int z) { + return z = 5 >> i; + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/assertExceptiontest6UninitializedContract.sol b/src/test/resources/soliditycode/assertExceptiontest6UninitializedContract.sol new file mode 100644 index 00000000000..1ff2215abdb --- /dev/null +++ b/src/test/resources/soliditycode/assertExceptiontest6UninitializedContract.sol @@ -0,0 +1,27 @@ +//pragma solidity ^0.4.0; +contract uni { +function b(int x, int y) internal returns (int) +{ + return x * y; +} + +function test1() external returns (int) +{ + // Variable containing a function pointer + function (int, int) internal returns (int) funcPtr; + + funcPtr = b; + + // This call to funcPtr will succeed + return funcPtr(4, 5); +} + +function test2() external returns (int) +{ + // Variable containing a function pointer + function (int, int) internal returns (int) funcPtr; + + // This call will fail because funcPtr is still a zero-initialized function pointer + return funcPtr(4, 5); +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/assertExceptiontest7TestAssertContract.sol b/src/test/resources/soliditycode/assertExceptiontest7TestAssertContract.sol new file mode 100644 index 00000000000..0bfd6fbd04e --- /dev/null +++ b/src/test/resources/soliditycode/assertExceptiontest7TestAssertContract.sol @@ -0,0 +1,15 @@ +pragma solidity >0.5.0; +contract TestThrowsContract{ + function testAssert() public{ + assert(1==2); + } + function testRequire() public{ + require(2==1); + } + function testRevert() public{ + revert(); + } + function testThrow() public{ + revert(); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/codeSaftySupport.sol b/src/test/resources/soliditycode/codeSaftySupport.sol new file mode 100644 index 00000000000..45a4beee384 --- /dev/null +++ b/src/test/resources/soliditycode/codeSaftySupport.sol @@ -0,0 +1,19 @@ +//pragma solidity ^0.4.24; + +contract IllegalDecorate { + +constructor() payable public{} + +function() payable external{} + +event log(uint256); + +function transferToken(address payable toAddress, uint256 tokenValue) public payable { +emit log(msg.value); +emit log(msg.tokenvalue); +emit log(msg.tokenid); +toAddress.transferToken(msg.tokenvalue, msg.tokenid); +toAddress.transfer(msg.value); +} + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/codeSaftyUnsupport.sol b/src/test/resources/soliditycode/codeSaftyUnsupport.sol new file mode 100644 index 00000000000..220d66b2257 --- /dev/null +++ b/src/test/resources/soliditycode/codeSaftyUnsupport.sol @@ -0,0 +1,56 @@ +//pragma solidity ^0.4.24; + +contract SubC { + +event log(string); + +function () payable external{} + +function receiveToken() payable public{} + +function getBalance() view public returns (uint256 r) { +r = address(this).balance; +} +} + +contract UseDot { +constructor() payable public{} +function() payable external{} +mapping(address => mapping(trcToken => uint256)) sender_tokens; + +function trigger1(address payable addr, trcToken tokenInputId) payable public { + //address(SubC(addr)).call.value(1000).tokenId(tokenInputId)(abi.encodeWithSignature("receiveToken()")); // ERROR +} + +function trigger2(address payable addr) payable public { +// addr.transferToken.value(10)(10, 0x6e6d62); // ERROR +} + +function trigger3(address payable addr) payable public { + // address(SubC(addr)).receiveToken.tokenvalue(10)(); // ERROR +} + +function trigger4(address payable addr) payable public { + //SubC(addr).receiveToken.tokenId(0x6e6d62)(); // ERROR +} + +function trigger5(address payable addr) payable public { + SubC(addr).receiveToken.value(10)(); +} + +function trigger6(address payable addr, trcToken tokenId) payable public { +address(SubC(addr)).call.value(1000)(abi.encodeWithSignature("transferToken(uint256, trcToken)", 10, tokenId)); +} + +function trigger7(address addr) payable public { + //sender_tokens[msg.sender][msg.tokenid] += msg.tokenvalue; // compile success, no necessary to trigger +} + +function trigger8(address addr) public payable returns(bytes memory r){ +// r = msg.data; // compile success, no necessary to trigger +} + +function getBalance() public returns (uint256 r){ +r = address(this).balance; +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/constantContract001.sol b/src/test/resources/soliditycode/constantContract001.sol new file mode 100644 index 00000000000..ab97b450235 --- /dev/null +++ b/src/test/resources/soliditycode/constantContract001.sol @@ -0,0 +1,8 @@ +//pragma solidity ^0.4.0; + +contract testConstantContract{ +function testPure(uint256 x,uint256 y) public pure returns (uint256 z) { +uint256 i=1; +return i + x + y; +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractGetterContract.sol b/src/test/resources/soliditycode/contractGetterContract.sol new file mode 100644 index 00000000000..ba090f061dd --- /dev/null +++ b/src/test/resources/soliditycode/contractGetterContract.sol @@ -0,0 +1,17 @@ +//pragma solidity ^0.4.0; + + +contract getterContract { + +constructor() public payable{} +function() external payable{} + +uint public c = msg.value; + +function getDataUsingAccessor() public payable returns (uint){ + +return c; + +} + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractGrammar001test1Grammar001.sol b/src/test/resources/soliditycode/contractGrammar001test1Grammar001.sol new file mode 100644 index 00000000000..1d0ad6e3d3f --- /dev/null +++ b/src/test/resources/soliditycode/contractGrammar001test1Grammar001.sol @@ -0,0 +1,18 @@ +pragma solidity >0.5.0; +contract FunctionSelector { + function select(bool useB, uint x) public returns (uint z) { + //var f = a; + //if (useB) f = b; + //return f(x); + if (useB) + return b(x); + else + return a(x); + } +function a(uint x) public returns (uint z) { + return x * x; + } +function b(uint x) public returns (uint z) { + return 2 * x; + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractGrammar001test2Grammar002.sol b/src/test/resources/soliditycode/contractGrammar001test2Grammar002.sol new file mode 100644 index 00000000000..df9d5c88839 --- /dev/null +++ b/src/test/resources/soliditycode/contractGrammar001test2Grammar002.sol @@ -0,0 +1,44 @@ +//pragma solidity ^0.4.16; +library Set { + // We define a new struct datatype that will be used to + // hold its data in the calling contract. + struct Data { mapping(uint => bool) flags; } + + // Note that the first parameter is of type "storage + // reference" and thus only its storage address and not + // its contents is passed as part of the call. This is a + // special feature of library functions. It is idiomatic + // to call the first parameter 'self', if the function can + // be seen as a method of that object. + function insert(Data storage self, uint value) public returns (bool) { + if (self.flags[value]) + return false; // already there + self.flags[value] = true; + return true; + } + + function remove(Data storage self, uint value) public returns (bool) { + if (!self.flags[value]) + return false; // not there + self.flags[value] = false; + return true; + } + + function contains(Data storage self, uint value) public returns (bool) { + return self.flags[value]; + } +} + + +contract C { + Set.Data knownValues; + + function register (uint value) public{ + // The library functions can be called without a + // specific instance of the library, since the + // "instance" will be the current contract. + if (!Set.insert(knownValues, value)) + revert(); + } + // In this contract, we can also directly access knownValues.flags, if we want. +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractGrammar001test3Grammar003.sol b/src/test/resources/soliditycode/contractGrammar001test3Grammar003.sol new file mode 100644 index 00000000000..ce56f5c9912 --- /dev/null +++ b/src/test/resources/soliditycode/contractGrammar001test3Grammar003.sol @@ -0,0 +1,44 @@ +//pragma solidity ^0.4.11; + +library Set { + struct Data { mapping(uint => bool) flags; } + + function insert(Data storage self, uint value) public + returns (bool) + { + if (self.flags[value]) + return false; // already there + self.flags[value] = true; + return true; + } + + function remove(Data storage self, uint value) public + returns (bool) + { + if (!self.flags[value]) + return false; // not there + self.flags[value] = false; + return true; + } + + function contains(Data storage self, uint value) public + returns (bool) + { + return self.flags[value]; + } +} + + +contract C { + using Set for Set.Data; // this is the crucial change + Set.Data knownValues; + + function register(uint value) public{ + // Here, all variables of type Set.Data have + // corresponding member functions. + // The following function call is identical to + // Set.insert(knownValues, value) + if (!knownValues.insert(value)) + revert(); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractGrammar001test4Grammar004.sol b/src/test/resources/soliditycode/contractGrammar001test4Grammar004.sol new file mode 100644 index 00000000000..b36d171a912 --- /dev/null +++ b/src/test/resources/soliditycode/contractGrammar001test4Grammar004.sol @@ -0,0 +1,31 @@ +//pragma solidity ^0.4.0; + +library Search { + function indexOf(uint[] storage self, uint value) public returns (uint) { + for (uint i = 0; i < self.length; i++) + if (self[i] == value) return i; + return uint(-1); + } +} + + +contract C { + using Search for uint[]; + uint[] public data; + + function append(uint value) public{ + data.push(value); + } + + function replace(uint _old, uint _new) public{ + // This performs the library function call + uint index = data.indexOf(_old); + if (index == uint(-1)) + data.push(_new); + else + data[index] = _new; + } + function getData(uint256 index) public returns(uint256){ + return data[index]; + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractGrammar001test5Grammar006.sol b/src/test/resources/soliditycode/contractGrammar001test5Grammar006.sol new file mode 100644 index 00000000000..805476a9e4a --- /dev/null +++ b/src/test/resources/soliditycode/contractGrammar001test5Grammar006.sol @@ -0,0 +1,38 @@ +// pragma solidity ^0.4.0; +contract InfoFeed { +function d1(uint x) public{ + assembly{ + function f(x) -> y { switch x case 0 { y := 1 } default { y := mul(x, f(sub(x, 1))) } } + } + } + function d2(uint x) public{ + assembly { x := mul(1, add(2, 3))} + } + function f(uint x) public{ + assembly { x := sub(x, 1) } + + } + function d(uint x) public{ + assembly{ + let x := add(2, 3) let y := mload(0x40) x := add(x, y) + } + } + function d4(uint x) public{ + // Error: The labels 'repeat' is disallowed. Please use "if", "switch", "for" or function calls instead + //assembly{let x := 10 repeat: x := sub(x, 1) jumpi(repeat, eq(x, 0)) + x = x; + //} + } + function d5(uint x) public{ + assembly{ + function f(x) -> y { switch x case 0 { y := mul(x, 2) } default { y := 0 } } + + } + } + + function d6(uint x) public{ + assembly{ + function f(x) -> y { for { let i := 0 } lt(i, x) { i := add(i, 1) } { y := mul(2, y) } } + } + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractGrammar002test1Grammar007_1.sol b/src/test/resources/soliditycode/contractGrammar002test1Grammar007_1.sol new file mode 100644 index 00000000000..6e3ac0bfd1e --- /dev/null +++ b/src/test/resources/soliditycode/contractGrammar002test1Grammar007_1.sol @@ -0,0 +1,60 @@ +//pragma solidity ^0.4.19; +contract Doug{ + mapping (bytes32 => uint) public contracts; + constructor() public{ + contracts['hww'] = 1; + contracts['brian'] = 2; + contracts['zzy'] = 7; + } + + function getDougName(string memory _name) public view returns(string memory) { + return _name; + } + + function getDougAge(uint _age) public pure returns(uint) { + return 3 ** _age; + } +} + +contract DogInterface { + function getDougAge(uint _age) public returns (uint); + function contracts(bytes32 name) public returns (uint); +} +contract main{ + + event FetchContract(address dogInterfaceAddress, address sender, bytes32 name); + + address public DOUG; + + address dogInterfaceAddress; + DogInterface dogContract ; + + function setDOUG(address _doug) public { + DOUG = _doug; + } + + constructor(address addr) public{ + dogInterfaceAddress = addr; + dogContract = DogInterface(dogInterfaceAddress); + } + + function dougOfage(uint _age) public returns(uint) { + + uint num = dogContract.getDougAge(_age); + return _age+num; + // return num; + } + + function uintOfName(bytes32 _name) public returns (uint) { + + dogContract.contracts(_name); + emit FetchContract(dogInterfaceAddress, msg.sender, _name); + + } + + // function getTest(string _name) public view returns(string) { + // string memory newName = _name ; + // DogInterface(DOUG).getDougName(newName); + // return newName; + // } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractGrammar002test1Grammar007_2.sol b/src/test/resources/soliditycode/contractGrammar002test1Grammar007_2.sol new file mode 100644 index 00000000000..6e3ac0bfd1e --- /dev/null +++ b/src/test/resources/soliditycode/contractGrammar002test1Grammar007_2.sol @@ -0,0 +1,60 @@ +//pragma solidity ^0.4.19; +contract Doug{ + mapping (bytes32 => uint) public contracts; + constructor() public{ + contracts['hww'] = 1; + contracts['brian'] = 2; + contracts['zzy'] = 7; + } + + function getDougName(string memory _name) public view returns(string memory) { + return _name; + } + + function getDougAge(uint _age) public pure returns(uint) { + return 3 ** _age; + } +} + +contract DogInterface { + function getDougAge(uint _age) public returns (uint); + function contracts(bytes32 name) public returns (uint); +} +contract main{ + + event FetchContract(address dogInterfaceAddress, address sender, bytes32 name); + + address public DOUG; + + address dogInterfaceAddress; + DogInterface dogContract ; + + function setDOUG(address _doug) public { + DOUG = _doug; + } + + constructor(address addr) public{ + dogInterfaceAddress = addr; + dogContract = DogInterface(dogInterfaceAddress); + } + + function dougOfage(uint _age) public returns(uint) { + + uint num = dogContract.getDougAge(_age); + return _age+num; + // return num; + } + + function uintOfName(bytes32 _name) public returns (uint) { + + dogContract.contracts(_name); + emit FetchContract(dogInterfaceAddress, msg.sender, _name); + + } + + // function getTest(string _name) public view returns(string) { + // string memory newName = _name ; + // DogInterface(DOUG).getDougName(newName); + // return newName; + // } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractGrammar002test2Grammar008.sol b/src/test/resources/soliditycode/contractGrammar002test2Grammar008.sol new file mode 100644 index 00000000000..c9c5d614d2d --- /dev/null +++ b/src/test/resources/soliditycode/contractGrammar002test2Grammar008.sol @@ -0,0 +1,14 @@ +//pragma solidity ^0.4.19; +contract Feline { + function utterance() public returns (bytes32); + + function getContractName() public returns (string memory){ + return "Feline"; + } +} + + +contract Cat is Feline { + function utterance() public returns (bytes32) { return "miaow"; } + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractGrammar002test3Grammar010.sol b/src/test/resources/soliditycode/contractGrammar002test3Grammar010.sol new file mode 100644 index 00000000000..a7749dfcc71 --- /dev/null +++ b/src/test/resources/soliditycode/contractGrammar002test3Grammar010.sol @@ -0,0 +1,10 @@ +//pragma solidity ^0.4.0; +contract InfoFeed { +function info() public payable returns (uint ret) { return 42; } +} +contract Consumer { +constructor() payable public{} +InfoFeed feed; +function setFeed(address addr) public { feed = InfoFeed(addr); } +function callFeed() public payable { feed.info.value(10).gas(800)(); } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractGrammar002test4Grammar011.sol b/src/test/resources/soliditycode/contractGrammar002test4Grammar011.sol new file mode 100644 index 00000000000..921b52a6080 --- /dev/null +++ b/src/test/resources/soliditycode/contractGrammar002test4Grammar011.sol @@ -0,0 +1,11 @@ +//pragma solidity ^0.4.0; +contract C { +function f(uint key, uint value) public returns(uint) { +return key; +// do something +} +function g() public { +// named arguments +f({value: 2, key: 3}); +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractGrammar002test4Grammar012.sol b/src/test/resources/soliditycode/contractGrammar002test4Grammar012.sol new file mode 100644 index 00000000000..45e6d3aaf6e --- /dev/null +++ b/src/test/resources/soliditycode/contractGrammar002test4Grammar012.sol @@ -0,0 +1,24 @@ +//pragma solidity ^0.4.24; +contract rTest { +function info() public payable returns (uint,address,bytes4,uint,uint,uint,address,uint) { +//function info() public payable returns (address ,uint,uint,uint,bytes32,uint,bytes,uint,address,bytes4,uint,uint,uint,address,uint) { +//var a = block.coinbase ; +//var b = block.difficulty; +//var c = block.gaslimit; +//var d = block.number; +//var e = block.blockhash(0); +//var e = d; +//var f = block.timestamp; +//bytes memory g = msg.data; +uint256 h = gasleft(); +address payable i = msg.sender; +bytes4 j = msg.sig; +uint256 k = msg.value; +uint256 l = now; +uint256 m = tx.gasprice; +address payable n = tx.origin; +uint256 o = address(this).balance; +return (h,i,j,k,l,m,n,o); +//return (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o); +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractGrammar002test6Grammar013.sol b/src/test/resources/soliditycode/contractGrammar002test6Grammar013.sol new file mode 100644 index 00000000000..56f97191ea0 --- /dev/null +++ b/src/test/resources/soliditycode/contractGrammar002test6Grammar013.sol @@ -0,0 +1,24 @@ +//pragma solidity ^0.4.4; +contract Counter { +uint count = 0; +address payable owner; +//function Counter() public{ +constructor() public{ +owner = msg.sender; +} +function increment() public { +uint step = 10; +if (owner == msg.sender) { +count = count + step; +} +} +function getCount() public returns (uint){ +return count; +} +function kill() public{ +if (owner == msg.sender) { +selfdestruct(owner); +//selfdestruct(address(owner)); +} +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractGrammar003test1Grammar014.sol b/src/test/resources/soliditycode/contractGrammar003test1Grammar014.sol new file mode 100644 index 00000000000..9190e902056 --- /dev/null +++ b/src/test/resources/soliditycode/contractGrammar003test1Grammar014.sol @@ -0,0 +1,68 @@ +//pragma solidity ^0.4.4; +contract A { +uint256 public numberForB; +address public senderForB; +function callTest(address bAddress, uint256 _number) public{ + +//bAddress.call(bytes4(sha3("setValue(uint256)")), _number); // B's storage is set, A is not modified +bAddress.call(abi.encodeWithSignature("setValue(uint256)",_number)); // B's storage is set, A is not modified +} +function callcodeTest(address bAddress, uint256 _number) public{ +//bAddress.callcode(bytes4(sha3("setValue(uint256)")), _number); // A's storage is set, B is not modified +bAddress.delegatecall(abi.encodeWithSignature("setValue(uint256)", _number)); // A's storage is set, B is not modified +} +function delegatecallTest(address bAddress, uint256 _number) public{ +//bAddress.delegatecall(bytes4(sha3("setValue(uint256)")), _number); // A's storage is set, B is not modified +bAddress.delegatecall(abi.encodeWithSignature("setValue(uint256)", _number)); // A's storage is set, B is not modified +} + +function callAddTest(address bAddress) public{ +//bAddress.call(bytes4(sha3("add()"))); // B's storage is set, A is not modified +bAddress.call(abi.encodeWithSignature("add()")); // B's storage is set, A is not modified +//bAddress.call(bytes4(sha3("add()"))); // B's storage is set, A is not modified +bAddress.call(abi.encodeWithSignature("add()")); // B's storage is set, A is not modified +} +function getnumberForB() public returns(uint256){ + return numberForB; + } + function getsenderForB() public returns(address){ + return senderForB; + } +} +contract B { +uint256 public numberForB; +address public senderForB; +address public addr11; +mapping(uint256=>address) public addr1; +mapping(uint256=>address) public addr2; +event ssss(uint256); +function setValue(uint256 _number) public{ + +emit ssss(_number); +numberForB = _number; +senderForB = msg.sender; +// senderForB is A if invoked by A's callTest. B's storage will be updated +// senderForB is A if invoked by A's callcodeTest. None of B's storage is updated +// senderForB is OWNER if invoked by A's delegatecallTest. None of B's storage is updated +} + +function add() public{ +numberForB=numberForB+1; +C c1 = new C(); +addr1[numberForB]=c1.getAddress(); +addr11 = c1.getAddress(); +C c2 = new C(); +addr2[numberForB] = c2.getAddress(); +} +function getnumberForB() public returns(uint256){ + return numberForB; + } + function getsenderForB() public returns(address){ + return senderForB; + } +} +contract C { +function getAddress() public view returns(address){ +return address(this); +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractGrammar003test2Grammar015.sol b/src/test/resources/soliditycode/contractGrammar003test2Grammar015.sol new file mode 100644 index 00000000000..51aa0843890 --- /dev/null +++ b/src/test/resources/soliditycode/contractGrammar003test2Grammar015.sol @@ -0,0 +1,39 @@ +//pragma solidity ^0.4.0; + +contract ExecuteFallback{ + + //回退事件,会把调用的数据打印出来 + event FallbackCalled(bytes data); + //fallback函数,注意是没有名字的,没有参数,没有返回值的 + function() external{ + emit FallbackCalled(msg.data); + } + + //调用已存在函数的事件,会把调用的原始数据,请求参数打印出来 + event ExistFuncCalled(bytes data, uint256 para); + //一个存在的函数 + function existFunc(uint256 para) public{ + emit ExistFuncCalled(msg.data, para); + } + + // 模拟从外部对一个存在的函数发起一个调用,将直接调用函数 + function callExistFunc() public{ + bytes4 funcIdentifier = bytes4(keccak256("existFunc(uint256)")); + //this.call(funcIdentifier, uint256(1)); + address(this).call(abi.encode(funcIdentifier, uint256(1))); + } + + //模拟从外部对一个不存在的函数发起一个调用,由于匹配不到函数,将调用回退函数 + function callNonExistFunc() public{ + bytes4 funcIdentifier = bytes4(keccak256("functionNotExist()")); + //this.call(funcIdentifier); + address(this).call(abi.encode(funcIdentifier)); + } + + function ExistFuncCalledTopic() view public returns(bytes32){ + return keccak256("ExistFuncCalled(bytes,uint256)"); + } + function FallbackCalledTopic() view public returns(bytes32){ + return keccak256("FallbackCalled(bytes)"); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractGrammar003test3Grammar016.sol b/src/test/resources/soliditycode/contractGrammar003test3Grammar016.sol new file mode 100644 index 00000000000..11eb8f9cc70 --- /dev/null +++ b/src/test/resources/soliditycode/contractGrammar003test3Grammar016.sol @@ -0,0 +1,23 @@ +//pragma solidity ^0.4.0; +contract C { +uint private data; +function f(uint a) private returns(uint b) { return a + 1; } +function setData(uint a) public { data = a; } +function getData() public returns(uint) { return data; } +function compute(uint a, uint b) internal returns (uint) { return a+b; } +} +contract D { +function readData() public{ +C c = new C(); +//uint local = c.f(7); // error: member "f" is not visible +c.setData(3); +uint local = c.getData(); +// local = c.compute(3, 5); // error: member "compute" is not visible +} +} +contract E is C { +function g() public { +C c = new C(); +uint val = compute(3, 5); // access to internal member (from derived to parent contract) +} +} diff --git a/src/test/resources/soliditycode/contractGrammar003test4Grammar017.sol b/src/test/resources/soliditycode/contractGrammar003test4Grammar017.sol new file mode 100644 index 00000000000..23fcdec76f0 --- /dev/null +++ b/src/test/resources/soliditycode/contractGrammar003test4Grammar017.sol @@ -0,0 +1,50 @@ +//pragma solidity ^0.4.0; +contract CrowdFunding{ +struct Funder{ +address addr; +uint amount; +} + +struct Campaign{ +address payable beneficiary; +uint goal; +uint amount; +uint funderNum; +mapping(uint => Funder) funders; +} + +uint compaingnID; +mapping (uint => Campaign) campaigns; + +function candidate(address payable beneficiary, uint goal) public payable returns (uint compaingnID){ +// initialize +campaigns[compaingnID++] = Campaign(beneficiary, goal, 0, 0); +} + +function vote(uint compaingnID) payable public { +Campaign storage c = campaigns[compaingnID]; + +//another way to initialize +c.funders[c.funderNum++] = Funder({addr: msg.sender, amount: msg.value}); +c.amount += msg.value; +} + +function check(uint comapingnId) public payable returns (bool){ + Campaign memory c = campaigns[comapingnId]; + + if(c.amount < c.goal){ + return false; + } + + uint amount = c.amount; + // incase send much more + c.amount = 0; + // address payable addr = address(uint160(c.beneficiary)); + //if(! addr.send(amount)){ + + if (! c.beneficiary.send(amount)){ + revert(); + } + return true; +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractGrammar003test5Grammar018.sol b/src/test/resources/soliditycode/contractGrammar003test5Grammar018.sol new file mode 100644 index 00000000000..ddd6deb040f --- /dev/null +++ b/src/test/resources/soliditycode/contractGrammar003test5Grammar018.sol @@ -0,0 +1,37 @@ +//pragma solidity ^0.4.0; + + +contract Grammar18{ + function testAddmod() public returns (uint z) { + //计算(x + y)%k,其中以任意精度执行加法,并且不在2 ** 256处围绕 + z=addmod(2, 2, 3); + return z; + } + function testMulmod() public returns (uint z) { +//计算(x * y)%k,其中乘法以任意精度执行,并且不会在2 ** 256处循环。 + z=mulmod(2, 3, 4); + return z; + } + + function testKeccak256() public returns(bytes32){ + //计算的(紧凑)参数的Ethereum-SHA-3(Keccak-256)的散列 + return keccak256("11"); + } + + function testSha256() public returns(bytes32){ + //计算(紧密包装)参数的SHA-256散列 + return sha256("11"); + } + function testSha3() public returns(bytes32){ + //计算(紧密包装)参数的SHA-256散列 + //return sha3("11"); + return keccak256("11"); + } + + function testRipemd160() public returns(bytes32){ + //计算(紧密包装)参数的RIPEMD-160哈希值 + return ripemd160("11"); + } + + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractGrammar003test6Grammar019.sol b/src/test/resources/soliditycode/contractGrammar003test6Grammar019.sol new file mode 100644 index 00000000000..30418539865 --- /dev/null +++ b/src/test/resources/soliditycode/contractGrammar003test6Grammar019.sol @@ -0,0 +1,12 @@ +//pragma solidity ^0.4.0; +contract timetest { + +constructor() public { +require( 1 == 1 seconds); +require(1 minutes == 60 seconds); +require(1 hours == 60 minutes); +require(1 days == 24 hours); +require(1 weeks == 7 days); +//require(1 years == 365 days); +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractGrammar003test7Grammar020.sol b/src/test/resources/soliditycode/contractGrammar003test7Grammar020.sol new file mode 100644 index 00000000000..1b960e6e313 --- /dev/null +++ b/src/test/resources/soliditycode/contractGrammar003test7Grammar020.sol @@ -0,0 +1,8 @@ +//pragma solidity ^0.4.0; +contract trxtest { + +function test() public { +require(1 trx == 1000000 sun); + +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractInnerContract.sol b/src/test/resources/soliditycode/contractInnerContract.sol new file mode 100644 index 00000000000..bc183931c88 --- /dev/null +++ b/src/test/resources/soliditycode/contractInnerContract.sol @@ -0,0 +1,32 @@ +//pragma solidity ^0.4.0; + + + +contract InnerContract { + + constructor() public payable{} + function() external payable{} + + function messageI() payable public returns (uint ret) { + + + + } + +} + + + +contract OuterContract { + + + constructor() public payable{} + function() external payable{} + + function callInner(address payable addr) payable public returns (uint) { + + return InnerContract(addr).messageI.value(1)(); + + } + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction001.sol b/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction001.sol new file mode 100644 index 00000000000..8baba262e87 --- /dev/null +++ b/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction001.sol @@ -0,0 +1,42 @@ +//pragma solidity ^0.4.24; + +contract A{ + constructor() payable public{} + function() payable external{} + function test1(address payable cAddr) public payable{ + B b1 = (new B).value(10)();//1.1 + B b2 = new B();//1.2 + address(b2).transfer(5);//1.3 + b2.callCGetZero(cAddr, 1);//1.4 + b2.callCGetZero(cAddr,2);//1.6 + } + function test2(address payable cAddress,uint256 amount) public payable{ + cAddress.call.value(amount)(abi.encodeWithSignature("newBAndTransfer()"));//2.1 + cAddress.call.value(amount + 1)(abi.encodeWithSignature("newBAndTransfer()"));//2.6 + } +} + +contract B{ + constructor() payable public{} + function() payable external{} + function getOne() payable public returns(uint256){ + return 1; + } + function callCGetZero(address payable cAddress,uint256 amount) public{ + cAddress.call.value(amount)(abi.encodeWithSignature("getZero()"));//1.5,1.7 + } +} + +contract C{ + constructor() payable public{} + function() payable external{} + function getZero() payable public returns(uint256){ + return 0; + } + function newBAndTransfer() payable public returns(uint256){ + B b1 = (new B).value(7)();//2.2,2.7 + b1.getOne();//2.3,2.8 + B b2 = (new B).value(3)();//2.4,2.9 + b2.getOne();//2.5,2.10 + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction002.sol b/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction002.sol new file mode 100644 index 00000000000..42231b7c960 --- /dev/null +++ b/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction002.sol @@ -0,0 +1,21 @@ +//pragma solidity ^0.4.24; + +contract A{ + constructor() payable public{} + function() payable external{} + + function test2(address cAddress,uint256 amount) public payable{ + //cAddress.call.value(amount)();//2.1 + cAddress.call.value(amount)("");//2.1 + } +} + + +contract C{ + constructor() payable public{} + function() payable external{} + function getZero() payable public returns(uint256){ + return 0; + } + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction003.sol b/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction003.sol new file mode 100644 index 00000000000..0910a0c4a2b --- /dev/null +++ b/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction003.sol @@ -0,0 +1,31 @@ +//pragma solidity ^0.4.24; + + contract A{ + uint256 public num = 0; + constructor() public payable{} + function transfer() payable public{ + B b = (new B).value(10)();//1 + + } + function getBalance() public returns(uint256){ + return address(this).balance; + } + } + contract B{ + uint256 public num = 0; + function f() payable public returns(bool) { + return true; + } + constructor() public payable {} + function payC(address payable c, bool isRevert) public{ + c.transfer(1);//4 + if (isRevert) { + revert(); + } + } + function getBalance() public returns(uint256){ + return address(this).balance; + } + function () payable external{} + } + diff --git a/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction004.sol b/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction004.sol new file mode 100644 index 00000000000..c7866dddb58 --- /dev/null +++ b/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction004.sol @@ -0,0 +1,25 @@ +//pragma solidity ^0.4.24; + +contract A{ + constructor () payable public{} + function test(address payable toAddress) public payable{ + selfdestruct(toAddress); + } + function () payable external{} + function getBalance() public view returns(uint256){ + return address(this).balance; + } +} +contract B{ + function() external payable{} + function kill(address contractAddres, address toAddress) payable public { + contractAddres.call(abi.encodeWithSignature("test(address)",address(this))); + } + function kill2() public{ + A a = new A(); + a.test(address(this)); + } + function getBalance() public view returns(uint256){ + return address(this).balance; + } +} diff --git a/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction005.sol b/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction005.sol new file mode 100644 index 00000000000..6e83c423b38 --- /dev/null +++ b/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction005.sol @@ -0,0 +1,54 @@ +//pragma solidity ^0.4.24; + +contract A{ + constructor() payable public{} + function() payable external{} + function test1() public payable{ + B b1 = (new B).value(10)();//1.1 + b1.callCGetZero(false); + b1.callCGetZero(true);//1.4 + } + function test2() public payable{ + C c1 = (new C).value(10)();//1.1 + c1.newBAndTransfer(false); + c1.newBAndTransfer(true);//1.4 + + } + function getBalance() view public returns(uint256){ + return address(this).balance; + } +} + +contract B{ + constructor() payable public{} + function() payable external{} + function getOne() payable public returns(uint256){ + return 1; + } + function callCGetZero(bool success) public payable{ + if(!success){ + assert(1==2); + } + } + function getBalance() view public returns(uint256){ + return address(this).balance; + } +} + +contract C{ + uint256 public flag=0; + constructor() payable public{} + function() payable external{} + function getZero() payable public returns(uint256){ + return 0; + } + function newBAndTransfer(bool success) payable public returns(uint256){ + flag = 1; + if(!success){ + require(2==1); + } + } + function getFlag() public returns(uint256){ + return flag; + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction006.sol b/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction006.sol new file mode 100644 index 00000000000..6bc548690a5 --- /dev/null +++ b/src/test/resources/soliditycode/contractInternalTransaction001testInternalTransaction006.sol @@ -0,0 +1,54 @@ +//pragma solidity ^0.4.24; + +contract A{ + constructor() payable public{} + function() payable external{} + function test1() public payable{ + B b1 = (new B).value(10)();//1.1 + b1.callCGetZero(true);//1.4 + b1.callCGetZero(false); + } + function test2() public payable{ + C c1 = (new C).value(10)();//1.1 + c1.newBAndTransfer(true);//1.4 + c1.newBAndTransfer(false); + + } + function getBalance() view public returns(uint256){ + return address(this).balance; + } +} + +contract B{ + constructor() payable public{} + function() payable external{} + function getOne() payable public returns(uint256){ + return 1; + } + function callCGetZero(bool success) public payable{ + if(!success){ + assert(1==2); + } + } + function getBalance() view public returns(uint256){ + return address(this).balance; + } +} + +contract C{ + uint256 public flag=0; + constructor() payable public{} + function() payable external{} + function getZero() payable public returns(uint256){ + return 0; + } + function newBAndTransfer(bool success) payable public returns(uint256){ + flag = 1; + if(!success){ + require(2==1); + } + } + function getFlag() public returns(uint256){ + return flag; + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractInternalTransaction002test1InternalTransaction007.sol b/src/test/resources/soliditycode/contractInternalTransaction002test1InternalTransaction007.sol new file mode 100644 index 00000000000..229bf82fa2d --- /dev/null +++ b/src/test/resources/soliditycode/contractInternalTransaction002test1InternalTransaction007.sol @@ -0,0 +1,38 @@ +//pragma solidity ^0.4.24; + +contract A{ + constructor() payable public{} + function() payable external{} + function test1(address cAddr) public payable{ + B b1 = (new B).value(10)();//1.1 + B b2 = new B();//1.2 + address(b2).transfer(5);//1.3 + b2.callCGetZero();//1.4 + } + function test2(address cAddress,uint256 amount) public payable{ + cAddress.call.value(amount)(abi.encodeWithSignature("newBAndTransfer()"));//2.1 + } +} + +contract B{ + constructor() payable public{} + function() payable external{} + function getOne() payable public returns(uint256){ + return 1; + } + function callCGetZero() public{ + assert(1==2); + + } +} + +contract C{ + constructor() payable public{} + function() payable external{} + function getZero() payable public returns(uint256){ + return 0; + } + function newBAndTransfer() payable public returns(uint256){ + require(2==1); + } +} diff --git a/src/test/resources/soliditycode/contractInternalTransaction002test2InternalTransaction008.sol b/src/test/resources/soliditycode/contractInternalTransaction002test2InternalTransaction008.sol new file mode 100644 index 00000000000..a75fba4f14b --- /dev/null +++ b/src/test/resources/soliditycode/contractInternalTransaction002test2InternalTransaction008.sol @@ -0,0 +1,60 @@ +//pragma solidity ^0.4.24; + +contract A{ + constructor() payable public{} + function() payable external{} + + function testAssert(address bAddress,uint256 amount) public payable{ + bAddress.call.value(amount).gas(1000000)(abi.encodeWithSignature("callCGetZero(bool)",false));//2.1 + bAddress.call.value(amount).gas(1000000)(abi.encodeWithSignature("callCGetZero(bool)",true)); + } + function testRequire(address cAddress,uint256 amount) public payable{ + cAddress.call.value(amount).gas(1000000)(abi.encodeWithSignature("newBAndTransfer(bool)",false));//2.1 + cAddress.call.value(amount).gas(1000000)(abi.encodeWithSignature("newBAndTransfer(bool)",true)); + } + function testAssert1(address bAddress,uint256 amount) public payable{ + bAddress.call.value(amount).gas(1000000)(abi.encodeWithSignature("callCGetZero(bool)",true)); + bAddress.call.value(amount).gas(1000000)(abi.encodeWithSignature("callCGetZero(bool)",false));//2.1 + } + function testtRequire2(address cAddress,uint256 amount) public payable{ + cAddress.call.value(amount).gas(1000000)(abi.encodeWithSignature("newBAndTransfer(bool)",true)); + cAddress.call.value(amount).gas(1000000)(abi.encodeWithSignature("newBAndTransfer(bool)",false));//2.1 + } + function getBalance() view public returns(uint256){ + return address(this).balance; + } +} + +contract B{ + constructor() payable public{} + function() payable external{} + function getOne() payable public returns(uint256){ + return 1; + } + function callCGetZero(bool success) payable public{ + if(!success){ + assert(1==2); + } + } + function getBalance() view public returns(uint256){ + return address(this).balance; + } +} + +contract C{ + uint256 public flag=0; + constructor() payable public{} + function() payable external{} + function getZero() payable public returns(uint256){ + return 0; + } + function newBAndTransfer(bool success) payable public returns(uint256){ + flag = 1; + if(!success){ + require(2==1); + } + } + function getFlag() public returns(uint256){ + return flag; + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractInternalTransaction002test3InternalTransaction009.sol b/src/test/resources/soliditycode/contractInternalTransaction002test3InternalTransaction009.sol new file mode 100644 index 00000000000..1a7df822511 --- /dev/null +++ b/src/test/resources/soliditycode/contractInternalTransaction002test3InternalTransaction009.sol @@ -0,0 +1,47 @@ +//pragma solidity ^0.4.24; + +contract A{ + constructor() payable public{} + function() payable external{} + function test1(address cAddr,address dcontract,address baddress) public payable{ + B b1 = (new B).value(10)();//1.1 + address(b1).transfer(5);//1.3 + b1.callCGetZero(cAddr, 1);//1.4 + b1.getOne(dcontract,baddress); + } +} + +contract B{ + constructor() payable public{} + function() payable external{} + function getOne(address contractAddres, address toAddress) payable public{ + contractAddres.call(abi.encodeWithSignature("suicide1(address)",address(this))); + + } + function callCGetZero(address cAddress,uint256 amount) public{ + cAddress.call.value(amount)(abi.encodeWithSignature("getZero()"));//1.5,1.7 + } +} + +contract C{ + constructor() payable public{} + function() payable external{} + function getZero() payable public returns(uint256){ + return 0; + } + function newBAndTransfer() payable public{ + B b1 = (new B).value(7)();//2.2,2.7 + B b2 = (new B).value(3)();//2.4,2.9 + } +} + +contract D{ + constructor () payable public{} + function suicide1(address payable toAddress) public payable{ + selfdestruct(toAddress); + } + function () payable external{} + function getBalance() public view returns(uint256){ + return address(this).balance; + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractInternalTransaction002test4InternalTransaction010.sol b/src/test/resources/soliditycode/contractInternalTransaction002test4InternalTransaction010.sol new file mode 100644 index 00000000000..7f34b2bfe08 --- /dev/null +++ b/src/test/resources/soliditycode/contractInternalTransaction002test4InternalTransaction010.sol @@ -0,0 +1,186 @@ +//pragma solidity ^0.4.24; + + contract A{ + uint256 public num = 0; + constructor() public payable{} + function transfer() payable public{ + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + + } + function transfer2() payable public{ + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + + } + function getBalance() public returns(uint256) { + return address(this).balance; + } + } + contract B{ + uint256 public num = 0; + function f() payable public returns(bool) { + return true; + } + constructor() public payable {} + function payC(address payable c, bool isRevert) public{ + c.transfer(1);//4 + if (isRevert) { + revert(); + } + } + function getBalance() public returns(uint256){ + return address(this).balance; + } + function () payable external{} + } + diff --git a/src/test/resources/soliditycode/contractInternalTransaction002test4InternalTransaction010_1.sol b/src/test/resources/soliditycode/contractInternalTransaction002test4InternalTransaction010_1.sol new file mode 100644 index 00000000000..c77fe76f5fa --- /dev/null +++ b/src/test/resources/soliditycode/contractInternalTransaction002test4InternalTransaction010_1.sol @@ -0,0 +1,210 @@ +pragma solidity ^0.4.24; + + contract A{ + uint256 public num = 0; + constructor() public payable{} + function transfer() payable public{ + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + } + function transfer2() payable public{ + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + + } + function getBalance() returns(uint256){ + return this.balance; + } + } + contract B{ + uint256 public num = 0; + function f() payable returns(bool) { + return true; + } + constructor() public payable {} + function payC(address c, bool isRevert) public{ + c.transfer(1);//4 + if (isRevert) { + revert(); + } + } + function getBalance() returns(uint256){ + return this.balance; + } + function () payable{} + } + + \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractInternalTransaction002test5InternalTransaction012.sol b/src/test/resources/soliditycode/contractInternalTransaction002test5InternalTransaction012.sol new file mode 100644 index 00000000000..ce2798888fe --- /dev/null +++ b/src/test/resources/soliditycode/contractInternalTransaction002test5InternalTransaction012.sol @@ -0,0 +1,51 @@ +//pragma solidity ^0.4.24; + +contract A{ + constructor() payable public{} + function() payable external{} + function test1(address bAddr,address eAddr) public payable{ + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + } + +} + +contract B{ + constructor() payable public{} + function() payable external{} + function getOne() payable public returns(uint256){ + return 1; + } + function testNN(address eAddress) public payable{ + D d1=(new D).value(1000)(); + d1.getOne(eAddress); + } +} + +contract C{ + constructor() payable public{} + function() payable external{} + function getZero() payable public returns(uint256){ + return 0; + } + function newBAndTransfer() payable public returns(uint256){ + require(2==1); + } +} +contract E{ + constructor() payable public{} + function() payable external{} + function getZero() payable public returns(uint256){ + return 0; + } + function newBAndTransfer() payable public returns(uint256){ + require(2==1); + } +} +contract D{ + constructor() payable public{} + function() payable external{} + function getOne(address eAddress) payable public returns(uint256){ + eAddress.call.value(1)(abi.encodeWithSignature("getZero()"));//2.1 + } + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction013.sol b/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction013.sol new file mode 100644 index 00000000000..bc1d3dbe6cd --- /dev/null +++ b/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction013.sol @@ -0,0 +1,56 @@ +//pragma solidity ^0.4.24; + +contract A{ + constructor() payable public{} + function() payable external{} + function test1(address dAddr) public payable{ + B b1 = (new B).value(10)();//1.1 + b1.testNN(dAddr,2);//1.6 + // C c1 = (new C).value(1000000000000)();//1.2 + // E e1 = (new E).value(1)();//1.2 + } + function test2(address cAddress,uint256 amount) public payable{ + cAddress.call.value(amount)(abi.encodeWithSignature("newBAndTransfer()"));//2.1 + } +} + +contract B{ + constructor() payable public{} + function() payable external{} + function getOne() payable public returns(uint256){ + return 1; + } + function testNN(address dAddress,uint256 amount) public payable{ + // D d1=(new D)(); + dAddress.call.value(amount)(abi.encodeWithSignature("getOne()"));//2.1 + } +} + +contract C{ + constructor() payable public{} + function() payable external{} + function getZero() payable public returns(uint256){ + return 0; + } + function newBAndTransfer() payable public returns(uint256){ + require(2==1); + } +} +contract E{ + constructor() payable public{} + function() payable external{} + function getZero() payable public returns(uint256){ + return 0; + } + function newBAndTransfer() payable public returns(uint256){ + require(2==1); + } +} +contract D{ + constructor() payable public{} + function() payable external{} + function getOne() payable public returns(uint256){ + E e = (new E).value(5)(); + } + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction014.sol b/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction014.sol new file mode 100644 index 00000000000..b3bbfc9a7db --- /dev/null +++ b/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction014.sol @@ -0,0 +1,38 @@ +contract callerContract { + constructor() payable public{} + function() payable external{} + function sendToB(address called_address,address c) public payable{ + called_address.delegatecall(abi.encodeWithSignature("transferTo(address)",c)); + } + function sendToB2(address called_address,address c) public payable{ + called_address.call(abi.encodeWithSignature("transferTo(address)",c)); + } + function sendToB3(address called_address,address c) public payable{ + called_address.delegatecall(abi.encodeWithSignature("transferTo(address)",c)); + } +} + + contract calledContract { + function() payable external {} + constructor() payable public{} + function transferTo(address payable toAddress)public payable{ + toAddress.transfer(5); + } + + function setIinC(address c) public payable{ + c.call.value(5)(abi.encodeWithSignature("setI()")); + } + + } + + contract c{ + uint256 public i=0; + constructor() public payable{} + function getBalance() public view returns(uint256){ + return address(this).balance; + } + function setI() payable public{ + i=5; + } + function() payable external{} + } diff --git a/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction015.sol b/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction015.sol new file mode 100644 index 00000000000..0426d650da4 --- /dev/null +++ b/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction015.sol @@ -0,0 +1,60 @@ +//pragma solidity ^0.4.24; + +contract A{ + constructor() payable public{} + function() payable external{} + function test1(address dAddr,address eAddr) public payable{ + B b1 = (new B).value(10)();//1.1 + b1.testNN(dAddr,2,eAddr);//1.6 + // C c1 = (new C).value(1000000000000)();//1.2 + // E e1 = (new E).value(1)();//1.2 + } + function test2(address cAddress,uint256 amount) public payable{ + cAddress.call.value(amount)(abi.encodeWithSignature("newBAndTransfer()"));//2.1 + } +} + +contract B{ + constructor() payable public{} + function() payable external{} + function getOne() payable public returns(uint256){ + return 1; + } + function testNN(address dAddress,uint256 amount,address eAddress) public payable{ + // D d1=(new D)(); + dAddress.call.value(amount)(abi.encodeWithSignature("getOne(address)",address(this)));//2.1 + } +} + +contract C{ + constructor() payable public{} + function() payable external{} + function getZero() payable public returns(uint256){ + return 0; + } + function newBAndTransfer() payable public returns(uint256){ + require(2==1); + } +} +contract E{ + constructor() payable public{} + function() payable external{} + function getZero() payable public returns(uint256){ + return 0; + } + function newBAndTransfer() payable public returns(uint256){ + require(2==1); + } + function suicide(address payable toAddress) public payable{ + selfdestruct(toAddress); + } +} +contract D{ + constructor() payable public{} + function() payable external{} + function getOne(address payable eAddress) payable public{ + E e = (new E).value(5)(); + e.suicide(eAddress); + } + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction016.sol b/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction016.sol new file mode 100644 index 00000000000..f97217fe169 --- /dev/null +++ b/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction016.sol @@ -0,0 +1,174 @@ +//pragma solidity ^0.4.24; + + contract A{ + uint256 public num = 0; + constructor() public payable{} + function () payable external{} + function transfer() payable public{ + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + B b1=(new B).value(1)();//1 + address payable aaa=address(this); + b1.suicide1(aaa); + } + function transfer2() payable public{ + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + B b1=(new B).value(1)();//1 + address payable aaa=address(this); + b1.suicide1(aaa); + } + function getBalance() public returns(uint256){ + return address(this).balance; + } + } + contract B{ + uint256 public num = 0; + function f() payable public returns(bool) { + return true; + } + constructor() public payable {} + function payC(address payable c, bool isRevert) public{ + c.transfer(1);//4 + if (isRevert) { + revert(); + } + } + function getBalance() public returns(uint256){ + return address(this).balance; + } + function () payable external{} + function suicide1(address payable toAddress) public payable{ + selfdestruct(toAddress); + } + } + diff --git a/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction017.sol b/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction017.sol new file mode 100644 index 00000000000..ebe570fd8af --- /dev/null +++ b/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction017.sol @@ -0,0 +1,199 @@ +//pragma solidity ^0.4.24; + + contract A{ + uint256 public num = 0; + constructor() public payable{} + function transfer(address payable Address) payable public{ + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + + B b=(new B).value(1)();//1 + selfdestruct(Address); + } + function transfer2() payable public{ + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + + } + function getBalance() public returns(uint256){ + return address(this).balance; + } + } + contract B{ + uint256 public num = 0; + function f() payable public returns(bool) { + return true; + } + constructor() public payable {} + function payC(address payable c, bool isRevert) public{ + c.transfer(1);//4 + if (isRevert) { + revert(); + } + } + function getBalance() public returns(uint256){ + return address(this).balance; + } + function () payable external{} + } + diff --git a/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction018.sol b/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction018.sol new file mode 100644 index 00000000000..a59c587b233 --- /dev/null +++ b/src/test/resources/soliditycode/contractInternalTransaction003testInternalTransaction018.sol @@ -0,0 +1,97 @@ +//pragma solidity ^0.4.24; + +contract A{ + constructor() payable public{} + function() payable external{} + function test1(address payable bAddr,address eAddr) public payable{ + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + bAddr.call.value(1)(abi.encodeWithSignature("testNN(address)",eAddr));//2.1 + + } + +} + +contract B{ + constructor() payable public{} + function() payable external{} + function getOne() payable public returns(uint256){ + return 1; + } + function testNN(address eAddress) public payable { + D d1=(new D).value(100)(); + d1.getOne(eAddress); + } +} + +contract C{ + constructor() payable public{} + function() payable external{} + function getZero() payable public returns(uint256){ + return 0; + } + function newBAndTransfer() payable public returns(uint256){ + require(2==1); + } +} +contract E{ + constructor() payable public{} + function() payable external{} + function getZero() payable public returns(uint256){ + return 0; + } + function newBAndTransfer() payable public returns(uint256){ + require(2==1); + } +} +contract D{ + constructor() payable public{} + function() payable external{} + function getOne(address eAddress) payable public returns(uint256){ + eAddress.call.value(1)(abi.encodeWithSignature("getZero()"));//2.1 + } + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractLinkage001.sol b/src/test/resources/soliditycode/contractLinkage001.sol new file mode 100644 index 00000000000..4c04cf5c6fb --- /dev/null +++ b/src/test/resources/soliditycode/contractLinkage001.sol @@ -0,0 +1,9 @@ +//pragma solidity ^0.4.0; + +contract divideIHaveArgsReturnStorage{ +constructor() payable public{} +function() payable external{} +function divideIHaveArgsReturn(int x,int y) public payable returns (int z) { +return z = x / y; +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractLinkage002.sol b/src/test/resources/soliditycode/contractLinkage002.sol new file mode 100644 index 00000000000..ca38896acee --- /dev/null +++ b/src/test/resources/soliditycode/contractLinkage002.sol @@ -0,0 +1,7 @@ +//pragma solidity ^0.4.0; + +contract divideIHaveArgsReturnStorage{ +function divideIHaveArgsReturn(int x,int y) public returns (int z) { +return z = x / y; +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractLinkage003.sol b/src/test/resources/soliditycode/contractLinkage003.sol new file mode 100644 index 00000000000..ca38896acee --- /dev/null +++ b/src/test/resources/soliditycode/contractLinkage003.sol @@ -0,0 +1,7 @@ +//pragma solidity ^0.4.0; + +contract divideIHaveArgsReturnStorage{ +function divideIHaveArgsReturn(int x,int y) public returns (int z) { +return z = x / y; +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractLinkage004.sol b/src/test/resources/soliditycode/contractLinkage004.sol new file mode 100644 index 00000000000..ca38896acee --- /dev/null +++ b/src/test/resources/soliditycode/contractLinkage004.sol @@ -0,0 +1,7 @@ +//pragma solidity ^0.4.0; + +contract divideIHaveArgsReturnStorage{ +function divideIHaveArgsReturn(int x,int y) public returns (int z) { +return z = x / y; +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractLinkage005.sol b/src/test/resources/soliditycode/contractLinkage005.sol new file mode 100644 index 00000000000..7b943aee5c1 --- /dev/null +++ b/src/test/resources/soliditycode/contractLinkage005.sol @@ -0,0 +1,51 @@ +contract timeoutTest { + string public iarray1; + // cpu + function oneCpu() public { + require(1==1); + } + + function storage8Char() public { + iarray1 = "12345678"; + } + + function testUseCpu(uint256 a) public returns (uint256){ + uint256 count = 0; + for (uint256 i = 0; i < a; i++) { + count++; + } + return count; + } + + + uint256[] public iarray; + uint public calculatedFibNumber; + mapping(address=>mapping(address=>uint256)) public m; + + function testUseStorage(uint256 a) public returns (uint256){ + uint256 count = 0; + for (uint256 i = 0; i < a; i++) { + count++; + iarray.push(i); + } + return count; + } + + // stack + //uint n = 0; + uint yy = 0; + function test() public { + //n += 1; + yy += 1; + test(); + } + + function setFibonacci(uint n) public returns (uint256){ + calculatedFibNumber = fibonacci(n); + return calculatedFibNumber; + } + + function fibonacci(uint n) internal returns (uint) { + return fibonacci(n - 1) + fibonacci(n - 2); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractLinkage006.sol b/src/test/resources/soliditycode/contractLinkage006.sol new file mode 100644 index 00000000000..9c20c82dc02 --- /dev/null +++ b/src/test/resources/soliditycode/contractLinkage006.sol @@ -0,0 +1,18 @@ +//pragma solidity ^0.4.0; +contract AA{ + uint256 public count=0; + constructor () payable public{} + function init(address payable addr, uint256 max) payable public { + count =0; + this.hack(addr,max); + } + function hack(address payable addr, uint256 max) payable public { + while (count < max) { + count = count +1; + this.hack(addr,max); + } + if (count == max) { + addr.send(20); + } + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractOriginEnergyLimit001.sol b/src/test/resources/soliditycode/contractOriginEnergyLimit001.sol new file mode 100644 index 00000000000..212614935f6 --- /dev/null +++ b/src/test/resources/soliditycode/contractOriginEnergyLimit001.sol @@ -0,0 +1,11 @@ +//pragma solidity ^0.4.0; + +contract findArgsContractTest{ + function findArgsByIndexTest(uint i) public returns (uint z) { + uint[] memory a = new uint[](3); + a[0]=1; + a[1]=2; + a[2]=3; + return a[i]; + } +} diff --git a/src/test/resources/soliditycode/contractOriginEnergyLimit004.sol b/src/test/resources/soliditycode/contractOriginEnergyLimit004.sol new file mode 100644 index 00000000000..212614935f6 --- /dev/null +++ b/src/test/resources/soliditycode/contractOriginEnergyLimit004.sol @@ -0,0 +1,11 @@ +//pragma solidity ^0.4.0; + +contract findArgsContractTest{ + function findArgsByIndexTest(uint i) public returns (uint z) { + uint[] memory a = new uint[](3); + a[0]=1; + a[1]=2; + a[2]=3; + return a[i]; + } +} diff --git a/src/test/resources/soliditycode/contractOtherToTrcToken.sol b/src/test/resources/soliditycode/contractOtherToTrcToken.sol new file mode 100644 index 00000000000..74afd5d0e54 --- /dev/null +++ b/src/test/resources/soliditycode/contractOtherToTrcToken.sol @@ -0,0 +1,41 @@ +//pragma solidity ^0.4.24; + +contract ConvertType { + +constructor() payable public{} + +function() payable external{} + +//function stringToTrctoken(address payable toAddress, string memory tokenStr, uint256 tokenValue) public { +// trcToken t = trcToken(tokenStr); // ERROR +// toAddress.transferToken(tokenValue, tokenStr); // ERROR +//} + +function uint256ToTrctoken(address payable toAddress, uint256 tokenValue, uint256 tokenInt) public { + trcToken t = trcToken(tokenInt); // OK + toAddress.transferToken(tokenValue, t); // OK + toAddress.transferToken(tokenValue, tokenInt); // OK +} + +function addressToTrctoken(address payable toAddress, uint256 tokenValue, address adr) public { + trcToken t = trcToken(adr); // OK + toAddress.transferToken(tokenValue, t); // OK +//toAddress.transferToken(tokenValue, adr); // ERROR +} + +//function bytesToTrctoken(address payable toAddress, bytes memory b, uint256 tokenValue) public { + // trcToken t = trcToken(b); // ERROR + // toAddress.transferToken(tokenValue, b); // ERROR +//} + +function bytes32ToTrctoken(address payable toAddress, uint256 tokenValue, bytes32 b32) public { + trcToken t = trcToken(b32); // OK + toAddress.transferToken(tokenValue, t); // OK +// toAddress.transferToken(tokenValue, b32); // ERROR +} + +//function arrayToTrctoken(address payable toAddress, uint256[] memory arr, uint256 tokenValue) public { +//trcToken t = trcToken(arr); // ERROR +// toAddress.transferToken(tokenValue, arr); // ERROR +//} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractScenario001.sol b/src/test/resources/soliditycode/contractScenario001.sol new file mode 100644 index 00000000000..ca38896acee --- /dev/null +++ b/src/test/resources/soliditycode/contractScenario001.sol @@ -0,0 +1,7 @@ +//pragma solidity ^0.4.0; + +contract divideIHaveArgsReturnStorage{ +function divideIHaveArgsReturn(int x,int y) public returns (int z) { +return z = x / y; +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractScenario002.sol b/src/test/resources/soliditycode/contractScenario002.sol new file mode 100644 index 00000000000..aa9deda79ef --- /dev/null +++ b/src/test/resources/soliditycode/contractScenario002.sol @@ -0,0 +1,53 @@ +//pragma solidity ^0.4.0; +contract TronNative{ + + address public voteContractAddress= address(0x10001); + address public freezeBalanceAddress = address(0x10002); + address public unFreezeBalanceAddress = address(0x10003); + address public withdrawBalanceAddress = address(0x10004); + address public approveProposalAddress = address(0x10005); + address public createProposalAddress = address(0x10006); + address public deleteProposalAddress = address(0x10007); + constructor () payable public {} + + function voteForSingleWitness (address payable witnessAddr, uint256 voteValue) public{ + // method 1: + voteContractAddress.delegatecall(abi.encode(witnessAddr,voteValue)); + } + + function voteUsingAssembly (address witnessAddr, uint256 voteValue) public{ + // method 2: + assembly{ + mstore(0x80,witnessAddr) + mstore(0xa0,voteValue) + // gas, address, in, size, out, size + if iszero(delegatecall(0, 0x10001, 0x80, 0x40, 0x80, 0x0)) { + revert(0, 0) + } + } + } + + function freezeBalance(uint256 frozen_Balance,uint256 frozen_Duration) public { + freezeBalanceAddress.delegatecall(abi.encode(frozen_Balance,frozen_Duration)); + } + + function unFreezeBalance() public { + unFreezeBalanceAddress.delegatecall(""); + } + + function withdrawBalance() public { + withdrawBalanceAddress.delegatecall(""); + } + + function approveProposal(uint256 id, bool isApprove) public { + approveProposalAddress.delegatecall(abi.encode(id,isApprove)); + } + + function createProposal(bytes32 [] memory data) public { + createProposalAddress.delegatecall(abi.encode(data)); + } + + function deleteProposal(uint256 id) public{ + deleteProposalAddress.delegatecall(abi.encode(id)); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractScenario003.sol b/src/test/resources/soliditycode/contractScenario003.sol new file mode 100644 index 00000000000..ca38896acee --- /dev/null +++ b/src/test/resources/soliditycode/contractScenario003.sol @@ -0,0 +1,7 @@ +//pragma solidity ^0.4.0; + +contract divideIHaveArgsReturnStorage{ +function divideIHaveArgsReturn(int x,int y) public returns (int z) { +return z = x / y; +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractScenario004.sol b/src/test/resources/soliditycode/contractScenario004.sol new file mode 100644 index 00000000000..b3ca2687b4c --- /dev/null +++ b/src/test/resources/soliditycode/contractScenario004.sol @@ -0,0 +1,88 @@ +//pragma solidity ^0.4.11; + +contract TronToken { + + string public name = "Tronix"; // token name + string public symbol = "TRX"; // token symbol + uint256 public decimals = 6; // token digit + + mapping (address => uint256) public balanceOf; + mapping (address => mapping (address => uint256)) public allowance; + + uint256 public totalSupply = 0; + bool public stopped = false; + + uint256 constant valueFounder = 100000000000000000; + address owner = address(0x0); + + modifier isOwner { + assert(owner == msg.sender); + _; + } + + modifier isRunning { + assert (!stopped); + _; + } + + modifier validAddress { + assert(address(0x0) != msg.sender); + _; + } + + constructor(address _addressFounder) public { + owner = msg.sender; + totalSupply = valueFounder; + balanceOf[_addressFounder] = valueFounder; + emit Transfer(address(0x0), _addressFounder, valueFounder); + } + + function transfer(address _to, uint256 _value) isRunning validAddress public returns (bool success) { + require(balanceOf[msg.sender] >= _value); + require(balanceOf[_to] + _value >= balanceOf[_to]); + balanceOf[msg.sender] -= _value; + balanceOf[_to] += _value; + emit Transfer(msg.sender, _to, _value); + return true; + } + + function transferFrom(address _from, address _to, uint256 _value) isRunning validAddress public returns (bool success) { + require(balanceOf[_from] >= _value); + require(balanceOf[_to] + _value >= balanceOf[_to]); + require(allowance[_from][msg.sender] >= _value); + balanceOf[_to] += _value; + balanceOf[_from] -= _value; + allowance[_from][msg.sender] -= _value; + emit Transfer(_from, _to, _value); + return true; + } + + function approve(address _spender, uint256 _value) isRunning validAddress public returns (bool success) { + require(_value == 0 || allowance[msg.sender][_spender] == 0); + allowance[msg.sender][_spender] = _value; + emit Approval(msg.sender, _spender, _value); + return true; + } + + function stop() isOwner public { + stopped = true; + } + + function start() isOwner public { + stopped = false; + } + + function setName(string memory _name) isOwner public { + name = _name; + } + + function burn(uint256 _value) public { + require(balanceOf[msg.sender] >= _value); + balanceOf[msg.sender] -= _value; + balanceOf[address(0x0)] += _value; + emit Transfer(msg.sender, address(0x0), _value); + } + + event Transfer(address indexed _from, address indexed _to, uint256 _value); + event Approval(address indexed _owner, address indexed _spender, uint256 _value); +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractScenario005.sol b/src/test/resources/soliditycode/contractScenario005.sol new file mode 100644 index 00000000000..d46098cd410 --- /dev/null +++ b/src/test/resources/soliditycode/contractScenario005.sol @@ -0,0 +1,103 @@ +//pragma solidity ^0.4.16; + +interface token { + function transfer(address receiver, uint amount) external; +} + +contract Crowdsale { + address payable public beneficiary = 0x1b228F5D9f934c7bb18Aaa86F90418932888E7b4; // 募资成功后的收款方 + uint public fundingGoal = 10000000; // 募资额度 + uint public amountRaised = 1000000; // 参与数量 + uint public deadline; // 募资截止期 + + uint public price; // token 与以太坊的汇率 , token卖多少钱 + token public tokenReward; // 要卖的token + + mapping(address => uint256) public balanceOf; + + bool fundingGoalReached = false; // 众筹是否达到目标 + bool crowdsaleClosed = false; // 众筹是否结束 + + /** + * 事件可以用来跟踪信息 + **/ + event GoalReached(address recipient, uint totalAmountRaised); + event FundTransfer(address backer, uint amount, bool isContribution); + + /** + * 构造函数, 设置相关属性 + */ + constructor( + address payable ifSuccessfulSendTo, + uint fundingGoalInEthers, + uint durationInMinutes, + uint finneyCostOfEachToken, + address addressOfTokenUsedAsReward) public{ + beneficiary = ifSuccessfulSendTo; + fundingGoal = fundingGoalInEthers * 1 sun; + deadline = now + durationInMinutes * 1 minutes; + price = finneyCostOfEachToken * 1 trx; + tokenReward = token(addressOfTokenUsedAsReward); // 传入已发布的 token 合约的地址来创建实例 + } + + /** + * 无函数名的Fallback函数, + * 在向合约转账时,这个函数会被调用 + */ + function () payable external{ + require(!crowdsaleClosed); + uint amount = msg.value; + balanceOf[msg.sender] += amount; + amountRaised += amount; + tokenReward.transfer(msg.sender, amount / price); + emit FundTransfer(msg.sender, amount, true); + } + + /** + * 定义函数修改器modifier(作用和Python的装饰器很相似) + * 用于在函数执行前检查某种前置条件(判断通过之后才会继续执行该方法) + * _ 表示继续执行之后的代码 + **/ + modifier afterDeadline() { if (now >= deadline) _; } + + /** + * 判断众筹是否完成融资目标, 这个方法使用了afterDeadline函数修改器 + * + */ + function checkGoalReached() afterDeadline public{ + if (amountRaised >= fundingGoal) { + fundingGoalReached = true; + emit GoalReached(beneficiary, amountRaised); + } + crowdsaleClosed = true; + } + + + /** + * 完成融资目标时,融资款发送到收款方 + * 未完成融资目标时,执行退款 + * + */ + function safeWithdrawal() afterDeadline public{ + if (!fundingGoalReached) { + uint amount = balanceOf[msg.sender]; + balanceOf[msg.sender] = 0; + if (amount > 0) { + if (msg.sender.send(amount)) { + emit FundTransfer(msg.sender, amount, false); + } else { + balanceOf[msg.sender] = amount; + } + } + } + + if (fundingGoalReached && beneficiary == msg.sender) { + if (address(beneficiary).send(amountRaised)) { + emit FundTransfer(beneficiary, amountRaised, false); + } else { + //If we fail to send the funds to beneficiary, unlock funders balance + fundingGoalReached = false; + } + } + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractScenario006.sol b/src/test/resources/soliditycode/contractScenario006.sol new file mode 100644 index 00000000000..397c62096e0 --- /dev/null +++ b/src/test/resources/soliditycode/contractScenario006.sol @@ -0,0 +1,1963 @@ +//pragma solidity ^0.4.24; + +interface PlayerBookInterface { + function getPlayerID(address _addr) external returns (uint256); + function getPlayerName(uint256 _pID) external view returns (bytes32); + function getPlayerLAff(uint256 _pID) external view returns (uint256); + function getPlayerAddr(uint256 _pID) external view returns (address); + function getNameFee() external view returns (uint256); + function registerNameXIDFromDapp(address _addr, bytes32 _name, uint256 _affCode, bool _all) external payable returns(bool, uint256); + function registerNameXaddrFromDapp(address _addr, bytes32 _name, address _affCode, bool _all) external payable returns(bool, uint256); + function registerNameXnameFromDapp(address _addr, bytes32 _name, bytes32 _affCode, bool _all) external payable returns(bool, uint256); + function isDev(address _who) external view returns(bool); +} + + +/** +* @title -Name Filter- v0.1.9 +* ┌┬┐┌─┐┌─┐┌┬┐ ╦╦ ╦╔═╗╔╦╗ ┌─┐┬─┐┌─┐┌─┐┌─┐┌┐┌┌┬┐┌─┐ +* │ ├┤ ├─┤│││ ║║ ║╚═╗ ║ ├─┘├┬┘├┤ └─┐├┤ │││ │ └─┐ +* ┴ └─┘┴ ┴┴ ┴ ╚╝╚═╝╚═╝ ╩ ┴ ┴└─└─┘└─┘└─┘┘└┘ ┴ └─┘ +* _____ _____ +* (, / /) /) /) (, / /) /) +* ┌─┐ / _ (/_ // // / _ // _ __ _(/ +* ├─┤ ___/___(/_/(__(_/_(/_(/_ ___/__/_)_(/_(_(_/ (_(_(_ +* ┴ ┴ / / .-/ _____ (__ / +* (__ / (_/ (, / /)™ +* / __ __ __ __ _ __ __ _ _/_ _ _(/ +* ┌─┐┬─┐┌─┐┌┬┐┬ ┬┌─┐┌┬┐ /__/ (_(__(_)/ (_/_)_(_)/ (_(_(_(__(/_(_(_ +* ├─┘├┬┘│ │ │││ ││ │ (__ / .-/ © Jekyll Island Inc. 2018 +* ┴ ┴└─└─┘─┴┘└─┘└─┘ ┴ (_/ +* _ __ _ ____ ____ _ _ _____ ____ ___ +*=============| |\ | / /\ | |\/| | |_ =====| |_ | | | | | | | |_ | |_)==============* +*=============|_| \| /_/--\ |_| | |_|__=====|_| |_| |_|__ |_| |_|__ |_| \==============* +* +* ╔═╗┌─┐┌┐┌┌┬┐┬─┐┌─┐┌─┐┌┬┐ ╔═╗┌─┐┌┬┐┌─┐ ┌──────────┐ +* ║ │ ││││ │ ├┬┘├─┤│ │ ║ │ │ ││├┤ │ Inventor │ +* ╚═╝└─┘┘└┘ ┴ ┴└─┴ ┴└─┘ ┴ ╚═╝└─┘─┴┘└─┘ └──────────┘ +*/ + +library NameFilter { + /** + * @dev filters name strings + * -converts uppercase to lower case. + * -makes sure it does not start/end with a space + * -makes sure it does not contain multiple spaces in a row + * -cannot be only numbers + * -cannot start with 0x + * -restricts characters to A-Z, a-z, 0-9, and space. + * @return reprocessed string in bytes32 format + */ + function nameFilter(string memory _input) + internal + pure + returns(bytes32) + { + bytes memory _temp = bytes(_input); + uint256 _length = _temp.length; + + //sorry limited to 32 characters + require (_length <= 32 && _length > 0, "string must be between 1 and 32 characters"); + // make sure it doesnt start with or end with space + require(_temp[0] != 0x20 && _temp[_length-1] != 0x20, "string cannot start or end with space"); + // make sure first two characters are not 0x + if (_temp[0] == 0x30) + { + require(_temp[1] != 0x78, "string cannot start with 0x"); + require(_temp[1] != 0x58, "string cannot start with 0X"); + } + + // create a bool to track if we have a non number character + bool _hasNonNumber; + + // convert & check + for (uint256 i = 0; i < _length; i++) + { + // if its uppercase A-Z + if (_temp[i] > 0x40 && _temp[i] < 0x5b) + { + // convert to lower case a-z + _temp[i] = byte(uint8(_temp[i]) + 32); + + // we have a non number + if (_hasNonNumber == false) + _hasNonNumber = true; + } else { + require + ( + // require character is a space + _temp[i] == 0x20 || + // OR lowercase a-z + (_temp[i] > 0x60 && _temp[i] < 0x7b) || + // or 0-9 + (_temp[i] > 0x2f && _temp[i] < 0x3a), + "string contains invalid characters" + ); + // make sure theres not 2x spaces in a row + if (_temp[i] == 0x20) + require( _temp[i+1] != 0x20, "string cannot contain consecutive spaces"); + + // see if we have a character other than a number + if (_hasNonNumber == false && (_temp[i] < 0x30 || _temp[i] > 0x39)) + _hasNonNumber = true; + } + } + + require(_hasNonNumber == true, "string cannot be only numbers"); + + bytes32 _ret; + assembly { + _ret := mload(add(_temp, 32)) + } + return (_ret); + } +} + + +library SafeMath { + + /** + * @dev Multiplies two numbers, throws on overflow. + */ + function mul(uint256 a, uint256 b) + internal + pure + returns (uint256 c) + { + if (a == 0) { + return 0; + } + c = a * b; + require(c / a == b, "SafeMath mul failed"); + return c; + } + + /** + * @dev Integer division of two numbers, truncating the quotient. + */ + function div(uint256 a, uint256 b) internal pure returns (uint256) { + // assert(b > 0); // Solidity automatically throws when dividing by 0 + uint256 c = a / b; + // assert(a == b * c + a % b); // There is no case in which this doesn't hold + return c; + } + + /** + * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). + */ + function sub(uint256 a, uint256 b) + internal + pure + returns (uint256) + { + require(b <= a, "SafeMath sub failed"); + return a - b; + } + + /** + * @dev Adds two numbers, throws on overflow. + */ + function add(uint256 a, uint256 b) + internal + pure + returns (uint256 c) + { + c = a + b; + require(c >= a, "SafeMath add failed"); + return c; + } + + /** + * @dev gives square root of given x. + */ + function sqrt(uint256 x) + internal + pure + returns (uint256 y) + { + uint256 z = ((add(x,1)) / 2); + y = x; + while (z < y) + { + y = z; + z = ((add((x / z),z)) / 2); + } + } + + /** + * @dev gives square. multiplies x by x + */ + function sq(uint256 x) + internal + pure + returns (uint256) + { + return (mul(x,x)); + } + + /** + * @dev x to the power of y + */ + function pwr(uint256 x, uint256 y) + internal + pure + returns (uint256) + { + if (x==0) + return (0); + else if (y==0) + return (1); + else + { + uint256 z = x; + for (uint256 i=1; i < y; i++) + z = mul(z,x); + return (z); + } + } +} + +//============================================================================== +// | _ _ _ | _ . +// |<(/_\/ (_(_||(_ . +//=======/====================================================================== +library F3DKeysCalcLong { + using SafeMath for *; + /** + * @dev calculates number of keys received given X eth + * @param _curEth current amount of eth in contract + * @param _newEth eth being spent + * @return amount of ticket purchased + */ + function keysRec(uint256 _curEth, uint256 _newEth) + internal + pure + returns (uint256) + { + return(keys((_curEth).add(_newEth)).sub(keys(_curEth))); + } + + /** + * @dev calculates amount of eth received if you sold X keys + * @param _curKeys current amount of keys that exist + * @param _sellKeys amount of keys you wish to sell + * @return amount of eth received + */ + function ethRec(uint256 _curKeys, uint256 _sellKeys) + internal + pure + returns (uint256) + { + return((eth(_curKeys)).sub(eth(_curKeys.sub(_sellKeys)))); + } + + /** + * @dev calculates how many keys would exist with given an amount of eth + * @param _eth eth "in contract" + * @return number of keys that would exist + */ + function keys(uint256 _eth) + internal + pure + returns(uint256) + { + return ((((((_eth).mul(1000000000000000000)).mul(312500000000000000000000000)).add(5624988281256103515625000000000000000000000000000000000000000000)).sqrt()).sub(74999921875000000000000000000000)) / (156250000); + } + + /** + * @dev calculates how much eth would be in contract given a number of keys + * @param _keys number of keys "in contract" + * @return eth that would exists + */ + function eth(uint256 _keys) + internal + pure + returns(uint256) + { + return ((78125000).mul(_keys.sq()).add(((149999843750000).mul(_keys.mul(1000000000000000000))) / (2))) / ((1000000000000000000).sq()); + } +} + +library F3Ddatasets { + //compressedData key + // [76-33][32][31][30][29][28-18][17][16-6][5-3][2][1][0] + // 0 - new player (bool) + // 1 - joined round (bool) + // 2 - new leader (bool) + // 3-5 - air drop tracker (uint 0-999) + // 6-16 - round end time + // 17 - winnerTeam + // 18 - 28 timestamp + // 29 - team + // 30 - 0 = reinvest (round), 1 = buy (round), 2 = buy (ico), 3 = reinvest (ico) + // 31 - airdrop happened bool + // 32 - airdrop tier + // 33 - airdrop amount won + //compressedIDs key + // [77-52][51-26][25-0] + // 0-25 - pID + // 26-51 - winPID + // 52-77 - rID + struct EventReturns { + uint256 compressedData; + uint256 compressedIDs; + address winnerAddr; // winner address + bytes32 winnerName; // winner name + uint256 amountWon; // amount won + uint256 newPot; // amount in new pot + uint256 P3DAmount; // amount distributed to p3d + uint256 genAmount; // amount distributed to gen + uint256 potAmount; // amount added to pot + } + struct Player { + address payable addr; // player address + bytes32 name; // player name + uint256 win; // winnings vault + uint256 gen; // general vault + uint256 aff; // affiliate vault + uint256 lrnd; // last round played + uint256 laff; // last affiliate id used + } + struct PlayerRounds { + uint256 eth; // eth player has added to round (used for eth limiter) + uint256 keys; // keys + uint256 mask; // player mask + uint256 ico; // ICO phase investment + } + struct Round { + uint256 plyr; // pID of player in lead + uint256 team; // tID of team in lead + uint256 end; // time ends/ended + bool ended; // has round end function been ran + uint256 strt; // time round started + uint256 keys; // keys + uint256 eth; // total eth in + uint256 pot; // eth to pot (during round) / final amount paid to winner (after round ends) + uint256 mask; // global mask + uint256 ico; // total eth sent in during ICO phase + uint256 icoGen; // total eth for gen during ICO phase + uint256 icoAvg; // average key price for ICO phase + } + struct TeamFee { + uint256 gen; // % of buy in thats paid to key holders of current round + uint256 p3d; // % of buy in thats paid to p3d holders + } + struct PotSplit { + uint256 gen; // % of pot thats paid to key holders of current round + uint256 p3d; // % of pot thats paid to p3d holders + } +} + +contract F3Devents { + // fired whenever a player registers a name + event onNewName + ( + uint256 indexed playerID, + address indexed playerAddress, + bytes32 indexed playerName, + bool isNewPlayer, + uint256 affiliateID, + address affiliateAddress, + bytes32 affiliateName, + uint256 amountPaid, + uint256 timeStamp + ); + + // fired at end of buy or reload + event onEndTx + ( + uint256 compressedData, + uint256 compressedIDs, + bytes32 playerName, + address playerAddress, + uint256 ethIn, + uint256 keysBought, + address winnerAddr, + bytes32 winnerName, + uint256 amountWon, + uint256 newPot, + uint256 P3DAmount, + uint256 genAmount, + uint256 potAmount, + uint256 airDropPot + ); + + // fired whenever theres a withdraw + event onWithdraw + ( + uint256 indexed playerID, + address playerAddress, + bytes32 playerName, + uint256 ethOut, + uint256 timeStamp + ); + + // fired whenever a withdraw forces end round to be ran + event onWithdrawAndDistribute + ( + address playerAddress, + bytes32 playerName, + uint256 ethOut, + uint256 compressedData, + uint256 compressedIDs, + address winnerAddr, + bytes32 winnerName, + uint256 amountWon, + uint256 newPot, + uint256 P3DAmount, + uint256 genAmount + ); + + // (fomo3d long only) fired whenever a player tries a buy after round timer + // hit zero, and causes end round to be ran. + event onBuyAndDistribute + ( + address playerAddress, + bytes32 playerName, + uint256 ethIn, + uint256 compressedData, + uint256 compressedIDs, + address winnerAddr, + bytes32 winnerName, + uint256 amountWon, + uint256 newPot, + uint256 P3DAmount, + uint256 genAmount + ); + + // (fomo3d long only) fired whenever a player tries a reload after round timer + // hit zero, and causes end round to be ran. + event onReLoadAndDistribute + ( + address playerAddress, + bytes32 playerName, + uint256 compressedData, + uint256 compressedIDs, + address winnerAddr, + bytes32 winnerName, + uint256 amountWon, + uint256 newPot, + uint256 P3DAmount, + uint256 genAmount + ); + + // fired whenever an affiliate is paid + event onAffiliatePayout + ( + uint256 indexed affiliateID, + address affiliateAddress, + bytes32 affiliateName, + uint256 indexed roundID, + uint256 indexed buyerID, + uint256 amount, + uint256 timeStamp + ); + + // received pot swap deposit + event onPotSwapDeposit + ( + uint256 roundID, + uint256 amountAddedToPot + ); +} + + + +contract FoMo3Dlong is F3Devents { + using SafeMath for *; + using NameFilter for string; + using F3DKeysCalcLong for uint256; + + address public otherF3D_; + address public Divies; + address public Jekyll_Island_Inc; + PlayerBookInterface public playerBook;// =PlayerBookInterface(0x0dcd2f752394c41875e259e00bb44fd505297caf);//new PlayerBook();// + // TeamJustInterface constant private teamJust = TeamJustInterface(0x3a5f8140b9213a0f733a6a639857c9df43ee3f5a);// new TeamJust();// + + //============================================================================== + // _ _ _ |`. _ _ _ |_ | _ _ . + // (_(_)| |~|~|(_||_|| (_||_)|(/__\ . (game settings) + //=================_|=========================================================== + string constant public name = "FoMo3D Long Official"; + string constant public symbol = "F3D"; + uint256 private rndExtra_ = 30;//extSettings.getLongExtra(); // length of the very first ICO + uint256 private rndGap_ = 30; //extSettings.getLongGap(); // length of ICO phase, set to 1 year for EOS. + uint256 constant private rndInit_ = 1 hours; // round timer starts at this + uint256 constant private rndInc_ = 30 seconds; // every full key purchased adds this much to the timer + uint256 constant private rndMax_ = 24 hours; // max length a round timer can be + //============================================================================== + // _| _ _|_ _ _ _ _|_ _ . + // (_|(_| | (_| _\(/_ | |_||_) . (data used to store game info that changes) + //=============================|================================================ + uint256 public airDropPot_; // person who gets the airdrop wins part of this pot + uint256 public airDropTracker_ = 0; // incremented each time a "qualified" tx occurs. used to determine winning air drop + uint256 public rID_; // round id number / total rounds that have happened + //**************** + // PLAYER DATA + //**************** + mapping(address => uint256) public pIDxAddr_; // (addr => pID) returns player id by address + mapping(bytes32 => uint256) public pIDxName_; // (name => pID) returns player id by name + mapping(uint256 => F3Ddatasets.Player) public plyr_; // (pID => data) player data + mapping(uint256 => mapping(uint256 => F3Ddatasets.PlayerRounds)) public plyrRnds_; // (pID => rID => data) player round data by player id & round id + mapping(uint256 => mapping(bytes32 => bool)) public plyrNames_; // (pID => name => bool) list of names a player owns. (used so you can change your display name amongst any name you own) + //**************** + // ROUND DATA + //**************** + mapping(uint256 => F3Ddatasets.Round) public round_; // (rID => data) round data + mapping(uint256 => mapping(uint256 => uint256)) public rndTmEth_; // (rID => tID => data) eth in per team, by round id and team id + //**************** + // TEAM FEE DATA + //**************** + mapping(uint256 => F3Ddatasets.TeamFee) public fees_; // (team => fees) fee distribution by team + mapping(uint256 => F3Ddatasets.PotSplit) public potSplit_; // (team => fees) pot split distribution by team + + function setPlayerBook(address _playerBook) external { + require(msg.sender == owner, 'only dev!'); + require(address(playerBook) == address(0), 'already set!'); + playerBook = PlayerBookInterface(_playerBook); + } + + address public owner; + + //============================================================================== + // _ _ _ __|_ _ __|_ _ _ . + // (_(_)| |_\ | | |_|(_ | (_)| . (initial data setup upon contract deploy) + //============================================================================== + constructor() + public + { + owner = msg.sender; + // Team allocation structures + // 0 = whales + // 1 = bears + // 2 = sneks + // 3 = bulls + + // Team allocation percentages + // (F3D, P3D) + (Pot , Referrals, Community) + // Referrals / Community rewards are mathematically designed to come from the winner's share of the pot. + fees_[0] = F3Ddatasets.TeamFee(30, 6); + //50% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot + fees_[1] = F3Ddatasets.TeamFee(43, 0); + //43% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot + fees_[2] = F3Ddatasets.TeamFee(56, 10); + //20% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot + fees_[3] = F3Ddatasets.TeamFee(43, 8); + //35% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot + + // how to split up the final pot based on which team was picked + // (F3D, P3D) + potSplit_[0] = F3Ddatasets.PotSplit(15, 10); + //48% to winner, 25% to next round, 2% to com + potSplit_[1] = F3Ddatasets.PotSplit(25, 0); + //48% to winner, 25% to next round, 2% to com + potSplit_[2] = F3Ddatasets.PotSplit(20, 20); + //48% to winner, 10% to next round, 2% to com + potSplit_[3] = F3Ddatasets.PotSplit(30, 10); + //48% to winner, 10% to next round, 2% to com + } + //============================================================================== + // _ _ _ _|. |`. _ _ _ . + // | | |(_)(_||~|~|(/_| _\ . (these are safety checks) + //============================================================================== + /** + * @dev used to make sure no one can interact with contract until it has + * been activated. + */ + modifier isActivated() { + require(activated_ == true, "its not ready yet. check ?eta in discord"); + _; + } + + /** + * @dev prevents contracts from interacting with fomo3d + */ + modifier isHuman() { + address _addr = msg.sender; + uint256 _codeLength; + + assembly {_codeLength := extcodesize(_addr)} + require(_codeLength == 0, "sorry humans only"); + _; + } + + modifier onlyDevs() + { + require(playerBook.isDev(msg.sender) == true, "msg sender is not a dev"); + _; + } + + /** + * @dev sets boundaries for incoming tx + */ + modifier isWithinLimits(uint256 _eth) { + require(_eth >= 1000000000, "pocket lint: not a valid currency"); + require(_eth <= 100000000000000000000000, "no vitalik, no"); + _; + } + + //============================================================================== + // _ |_ |. _ |` _ __|_. _ _ _ . + // |_)|_||_)||(_ ~|~|_|| |(_ | |(_)| |_\ . (use these to interact with contract) + //====|========================================================================= + /** + * @dev emergency buy uses last stored affiliate ID and team snek + */ + function() + isActivated() + isHuman() + isWithinLimits(msg.value) + external + payable + { + // set up our tx event data and determine if player is new or not + F3Ddatasets.EventReturns memory _eventData_ ; + _eventData_ = determinePID(_eventData_); + + // fetch player id + uint256 _pID = pIDxAddr_[msg.sender]; + + // buy core + buyCore(_pID, plyr_[_pID].laff, 2, _eventData_); + } + + /** + * @dev converts all incoming ethereum to keys. + * -functionhash- 0x8f38f309 (using ID for affiliate) + * -functionhash- 0x98a0871d (using address for affiliate) + * -functionhash- 0xa65b37a1 (using name for affiliate) + * @param _affCode the ID/address/name of the player who gets the affiliate fee + * @param _team what team is the player playing for? + */ + function buyXid(uint256 _affCode, uint256 _team) + isActivated() + isHuman() + isWithinLimits(msg.value) + public + payable + { + // set up our tx event data and determine if player is new or not + F3Ddatasets.EventReturns memory _eventData_; + _eventData_ = determinePID(_eventData_); + + // fetch player id + uint256 _pID = pIDxAddr_[msg.sender]; + + // manage affiliate residuals + // if no affiliate code was given or player tried to use their own, lolz + if (_affCode == 0 || _affCode == _pID) + { + // use last stored affiliate code + _affCode = plyr_[_pID].laff; + + // if affiliate code was given & its not the same as previously stored + } else if (_affCode != plyr_[_pID].laff) { + // update last affiliate + plyr_[_pID].laff = _affCode; + } + + // verify a valid team was selected + _team = verifyTeam(_team); + + // buy core + buyCore(_pID, _affCode, _team, _eventData_); + } + + function buyXaddr(address _affCode, uint256 _team) + isActivated() + isHuman() + isWithinLimits(msg.value) + public + payable + { + // set up our tx event data and determine if player is new or not + F3Ddatasets.EventReturns memory _eventData_; + _eventData_ = determinePID(_eventData_); + + // fetch player id + uint256 _pID = pIDxAddr_[msg.sender]; + + // manage affiliate residuals + uint256 _affID; + // if no affiliate code was given or player tried to use their own, lolz + if (_affCode == address(0) || _affCode == msg.sender) + { + // use last stored affiliate code + _affID = plyr_[_pID].laff; + + // if affiliate code was given + } else { + // get affiliate ID from aff Code + _affID = pIDxAddr_[_affCode]; + + // if affID is not the same as previously stored + if (_affID != plyr_[_pID].laff) + { + // update last affiliate + plyr_[_pID].laff = _affID; + } + } + + // verify a valid team was selected + _team = verifyTeam(_team); + + // buy core + buyCore(_pID, _affID, _team, _eventData_); + } + + function buyXname(bytes32 _affCode, uint256 _team) + isActivated() + isHuman() + isWithinLimits(msg.value) + public + payable + { + // set up our tx event data and determine if player is new or not + F3Ddatasets.EventReturns memory _eventData_ ; + _eventData_ = determinePID(_eventData_); + + // fetch player id + uint256 _pID = pIDxAddr_[msg.sender]; + + // manage affiliate residuals + uint256 _affID; + // if no affiliate code was given or player tried to use their own, lolz + if (_affCode == '' || _affCode == plyr_[_pID].name) + { + // use last stored affiliate code + _affID = plyr_[_pID].laff; + + // if affiliate code was given + } else { + // get affiliate ID from aff Code + _affID = pIDxName_[_affCode]; + + // if affID is not the same as previously stored + if (_affID != plyr_[_pID].laff) + { + // update last affiliate + plyr_[_pID].laff = _affID; + } + } + + // verify a valid team was selected + _team = verifyTeam(_team); + + // buy core + buyCore(_pID, _affID, _team, _eventData_); + } + + /** + * @dev essentially the same as buy, but instead of you sending ether + * from your wallet, it uses your unwithdrawn earnings. + * -functionhash- 0x349cdcac (using ID for affiliate) + * -functionhash- 0x82bfc739 (using address for affiliate) + * -functionhash- 0x079ce327 (using name for affiliate) + * @param _affCode the ID/address/name of the player who gets the affiliate fee + * @param _team what team is the player playing for? + * @param _eth amount of earnings to use (remainder returned to gen vault) + */ + function reLoadXid(uint256 _affCode, uint256 _team, uint256 _eth) + isActivated() + isHuman() + isWithinLimits(_eth) + public + { + // set up our tx event data + F3Ddatasets.EventReturns memory _eventData_; + + // fetch player ID + uint256 _pID = pIDxAddr_[msg.sender]; + + // manage affiliate residuals + // if no affiliate code was given or player tried to use their own, lolz + if (_affCode == 0 || _affCode == _pID) + { + // use last stored affiliate code + _affCode = plyr_[_pID].laff; + + // if affiliate code was given & its not the same as previously stored + } else if (_affCode != plyr_[_pID].laff) { + // update last affiliate + plyr_[_pID].laff = _affCode; + } + + // verify a valid team was selected + _team = verifyTeam(_team); + + // reload core + reLoadCore(_pID, _affCode, _team, _eth, _eventData_); + } + + function reLoadXaddr(address _affCode, uint256 _team, uint256 _eth) + isActivated() + isHuman() + isWithinLimits(_eth) + public + { + // set up our tx event data + F3Ddatasets.EventReturns memory _eventData_; + + // fetch player ID + uint256 _pID = pIDxAddr_[msg.sender]; + + // manage affiliate residuals + uint256 _affID; + // if no affiliate code was given or player tried to use their own, lolz + if (_affCode == address(0) || _affCode == msg.sender) + { + // use last stored affiliate code + _affID = plyr_[_pID].laff; + + // if affiliate code was given + } else { + // get affiliate ID from aff Code + _affID = pIDxAddr_[_affCode]; + + // if affID is not the same as previously stored + if (_affID != plyr_[_pID].laff) + { + // update last affiliate + plyr_[_pID].laff = _affID; + } + } + + // verify a valid team was selected + _team = verifyTeam(_team); + + // reload core + reLoadCore(_pID, _affID, _team, _eth, _eventData_); + } + + function reLoadXname(bytes32 _affCode, uint256 _team, uint256 _eth) + isActivated() + isHuman() + isWithinLimits(_eth) + public + { + // set up our tx event data + F3Ddatasets.EventReturns memory _eventData_; + + // fetch player ID + uint256 _pID = pIDxAddr_[msg.sender]; + + // manage affiliate residuals + uint256 _affID; + // if no affiliate code was given or player tried to use their own, lolz + if (_affCode == '' || _affCode == plyr_[_pID].name) + { + // use last stored affiliate code + _affID = plyr_[_pID].laff; + + // if affiliate code was given + } else { + // get affiliate ID from aff Code + _affID = pIDxName_[_affCode]; + + // if affID is not the same as previously stored + if (_affID != plyr_[_pID].laff) + { + // update last affiliate + plyr_[_pID].laff = _affID; + } + } + + // verify a valid team was selected + _team = verifyTeam(_team); + + // reload core + reLoadCore(_pID, _affID, _team, _eth, _eventData_); + } + + /** + * @dev withdraws all of your earnings. + * -functionhash- 0x3ccfd60b + */ + function withdraw() + isActivated() + isHuman() + public + { + // setup local rID + uint256 _rID = rID_; + + // grab time + uint256 _now = now; + + // fetch player ID + uint256 _pID = pIDxAddr_[msg.sender]; + + // setup temp var for player eth + uint256 _eth; + + // check to see if round has ended and no one has run round end yet + if (_now > round_[_rID].end && round_[_rID].ended == false && round_[_rID].plyr != 0) + { + // set up our tx event data + F3Ddatasets.EventReturns memory _eventData_; + + // end the round (distributes pot) + round_[_rID].ended = true; + _eventData_ = endRound(_eventData_); + + // get their earnings + _eth = withdrawEarnings(_pID); + + // gib moni + if (_eth > 0) + plyr_[_pID].addr.transfer(_eth); + + // build event data + _eventData_.compressedData = _eventData_.compressedData + (_now * 1000000000000000000); + _eventData_.compressedIDs = _eventData_.compressedIDs + _pID; + + // fire withdraw and distribute event + emit F3Devents.onWithdrawAndDistribute + ( + msg.sender, + plyr_[_pID].name, + _eth, + _eventData_.compressedData, + _eventData_.compressedIDs, + _eventData_.winnerAddr, + _eventData_.winnerName, + _eventData_.amountWon, + _eventData_.newPot, + _eventData_.P3DAmount, + _eventData_.genAmount + ); + + // in any other situation + } else { + // get their earnings + _eth = withdrawEarnings(_pID); + + // gib moni + if (_eth > 0) + plyr_[_pID].addr.transfer(_eth); + + // fire withdraw event + emit F3Devents.onWithdraw(_pID, msg.sender, plyr_[_pID].name, _eth, _now); + } + } + + /** + * @dev use these to register names. they are just wrappers that will send the + * registration requests to the PlayerBook contract. So registering here is the + * same as registering there. UI will always display the last name you registered. + * but you will still own all previously registered names to use as affiliate + * links. + * - must pay a registration fee. + * - name must be unique + * - names will be converted to lowercase + * - name cannot start or end with a space + * - cannot have more than 1 space in a row + * - cannot be only numbers + * - cannot start with 0x + * - name must be at least 1 char + * - max length of 32 characters long + * - allowed characters: a-z, 0-9, and space + * -functionhash- 0x921dec21 (using ID for affiliate) + * -functionhash- 0x3ddd4698 (using address for affiliate) + * -functionhash- 0x685ffd83 (using name for affiliate) + * @param _nameString players desired name + * @param _affCode affiliate ID, address, or name of who referred you + * @param _all set to true if you want this to push your info to all games + * (this might cost a lot of gas) + */ + function registerNameXID(string memory _nameString, uint256 _affCode, bool _all) + isHuman() + public + payable + { + bytes32 _name = _nameString.nameFilter(); + address _addr = msg.sender; + uint256 _paid = msg.value; + (bool _isNewPlayer, uint256 _affID) = playerBook.registerNameXIDFromDapp.value(_paid)(_addr, _name, _affCode, _all); + + uint256 _pID = pIDxAddr_[_addr]; + + // fire event + emit F3Devents.onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, _paid, now); + } + + function registerNameXaddr(string memory _nameString, address _affCode, bool _all) + isHuman() + public + payable + { + bytes32 _name = _nameString.nameFilter(); + address _addr = msg.sender; + uint256 _paid = msg.value; + (bool _isNewPlayer, uint256 _affID) = playerBook.registerNameXaddrFromDapp.value(msg.value)(msg.sender, _name, _affCode, _all); + + uint256 _pID = pIDxAddr_[_addr]; + + // fire event + emit F3Devents.onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, _paid, now); + } + + function registerNameXname(string memory _nameString, bytes32 _affCode, bool _all) + isHuman() + public + payable + { + bytes32 _name = _nameString.nameFilter(); + address _addr = msg.sender; + uint256 _paid = msg.value; + (bool _isNewPlayer, uint256 _affID) = playerBook.registerNameXnameFromDapp.value(msg.value)(msg.sender, _name, _affCode, _all); + + uint256 _pID = pIDxAddr_[_addr]; + + // fire event + emit F3Devents.onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, _paid, now); + } + //============================================================================== + // _ _ _|__|_ _ _ _ . + // (_|(/_ | | (/_| _\ . (for UI & viewing things on etherscan) + //=====_|======================================================================= + /** + * @dev return the price buyer will pay for next 1 individual key. + * -functionhash- 0x018a25e8 + * @return price for next key bought (in wei format) + */ + function getBuyPrice() + public + view + returns (uint256) + { + // setup local rID + uint256 _rID = rID_; + + // grab time + uint256 _now = now; + + // are we in a round? + if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) + return ((round_[_rID].keys.add(1000000000000000000)).ethRec(1000000000000000000)); + else // rounds over. need price for new round + return (75000000000000); + // init + } + + /** + * @dev returns time left. dont spam this, you'll ddos yourself from your node + * provider + * -functionhash- 0xc7e284b8 + * @return time left in seconds + */ + function getTimeLeft() + public + view + returns (uint256) + { + // setup local rID + uint256 _rID = rID_; + + // grab time + uint256 _now = now; + + if (_now < round_[_rID].end) + if (_now > round_[_rID].strt + rndGap_) + return ((round_[_rID].end).sub(_now)); + else + return ((round_[_rID].strt + rndGap_).sub(_now)); + else + return (0); + } + + /** + * @dev returns player earnings per vaults + * -functionhash- 0x63066434 + * @return winnings vault + * @return general vault + * @return affiliate vault + */ + function getPlayerVaults(uint256 _pID) + public + view + returns (uint256, uint256, uint256) + { + // setup local rID + uint256 _rID = rID_; + + // if round has ended. but round end has not been run (so contract has not distributed winnings) + if (now > round_[_rID].end && round_[_rID].ended == false && round_[_rID].plyr != 0) + { + // if player is winner + if (round_[_rID].plyr == _pID) + { + return + ( + (plyr_[_pID].win).add(((round_[_rID].pot).mul(48)) / 100), + (plyr_[_pID].gen).add(getPlayerVaultsHelper(_pID, _rID).sub(plyrRnds_[_pID][_rID].mask)), + plyr_[_pID].aff + ); + // if player is not the winner + } else { + return + ( + plyr_[_pID].win, + (plyr_[_pID].gen).add(getPlayerVaultsHelper(_pID, _rID).sub(plyrRnds_[_pID][_rID].mask)), + plyr_[_pID].aff + ); + } + + // if round is still going on, or round has ended and round end has been ran + } else { + return + ( + plyr_[_pID].win, + (plyr_[_pID].gen).add(calcUnMaskedEarnings(_pID, plyr_[_pID].lrnd)), + plyr_[_pID].aff + ); + } + } + + /** + * solidity hates stack limits. this lets us avoid that hate + */ + function getPlayerVaultsHelper(uint256 _pID, uint256 _rID) + private + view + returns (uint256) + { + return (((((round_[_rID].mask).add(((((round_[_rID].pot).mul(potSplit_[round_[_rID].team].gen)) / 100).mul(1000000000000000000)) / (round_[_rID].keys))).mul(plyrRnds_[_pID][_rID].keys)) / 1000000000000000000)); + } + + /** + * @dev returns all current round info needed for front end + * -functionhash- 0x747dff42 + * @return eth invested during ICO phase + * @return round id + * @return total keys for round + * @return time round ends + * @return time round started + * @return current pot + * @return current team ID & player ID in lead + * @return current player in leads address + * @return current player in leads name + * @return whales eth in for round + * @return bears eth in for round + * @return sneks eth in for round + * @return bulls eth in for round + * @return airdrop tracker # & airdrop pot + */ + function getCurrentRoundInfo() + public + view + returns (uint256, uint256, uint256, uint256, uint256, uint256, uint256, address, bytes32, uint256, uint256, uint256, uint256, uint256) + { + // setup local rID + uint256 _rID = rID_; + + return + ( + round_[_rID].ico, //0 + _rID, //1 + round_[_rID].keys, //2 + round_[_rID].end, //3 + round_[_rID].strt, //4 + round_[_rID].pot, //5 + (round_[_rID].team + (round_[_rID].plyr * 10)), //6 + plyr_[round_[_rID].plyr].addr, //7 + plyr_[round_[_rID].plyr].name, //8 + rndTmEth_[_rID][0], //9 + rndTmEth_[_rID][1], //10 + rndTmEth_[_rID][2], //11 + rndTmEth_[_rID][3], //12 + airDropTracker_ + (airDropPot_ * 1000) //13 + ); + } + + /** + * @dev returns player info based on address. if no address is given, it will + * use msg.sender + * -functionhash- 0xee0b5d8b + * @param _addr address of the player you want to lookup + * @return player ID + * @return player name + * @return keys owned (current round) + * @return winnings vault + * @return general vault + * @return affiliate vault + * @return player round eth + */ + function getPlayerInfoByAddress(address _addr) + public + view + returns (uint256, bytes32, uint256, uint256, uint256, uint256, uint256) + { + // setup local rID + uint256 _rID = rID_; + + if (_addr == address(0)) + { + _addr == msg.sender; + } + uint256 _pID = pIDxAddr_[_addr]; + + return + ( + _pID, //0 + plyr_[_pID].name, //1 + plyrRnds_[_pID][_rID].keys, //2 + plyr_[_pID].win, //3 + (plyr_[_pID].gen).add(calcUnMaskedEarnings(_pID, plyr_[_pID].lrnd)), //4 + plyr_[_pID].aff, //5 + plyrRnds_[_pID][_rID].eth //6 + ); + } + + //============================================================================== + // _ _ _ _ | _ _ . _ . + // (_(_)| (/_ |(_)(_||(_ . (this + tools + calcs + modules = our softwares engine) + //=====================_|======================================================= + /** + * @dev logic runs whenever a buy order is executed. determines how to handle + * incoming eth depending on if we are in an active round or not + */ + function buyCore(uint256 _pID, uint256 _affID, uint256 _team, F3Ddatasets.EventReturns memory _eventData_) + private + { + // setup local rID + uint256 _rID = rID_; + + // grab time + uint256 _now = now; + + // if round is active + if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) + { + // call core + core(_rID, _pID, msg.value, _affID, _team, _eventData_); + + // if round is not active + } else { + // check to see if end round needs to be ran + if (_now > round_[_rID].end && round_[_rID].ended == false) + { + // end the round (distributes pot) & start new round + round_[_rID].ended = true; + _eventData_ = endRound(_eventData_); + + // build event data + _eventData_.compressedData = _eventData_.compressedData + (_now * 1000000000000000000); + _eventData_.compressedIDs = _eventData_.compressedIDs + _pID; + + // fire buy and distribute event + emit F3Devents.onBuyAndDistribute + ( + msg.sender, + plyr_[_pID].name, + msg.value, + _eventData_.compressedData, + _eventData_.compressedIDs, + _eventData_.winnerAddr, + _eventData_.winnerName, + _eventData_.amountWon, + _eventData_.newPot, + _eventData_.P3DAmount, + _eventData_.genAmount + ); + } + + // put eth in players vault + plyr_[_pID].gen = plyr_[_pID].gen.add(msg.value); + } + } + + /** + * @dev logic runs whenever a reload order is executed. determines how to handle + * incoming eth depending on if we are in an active round or not + */ + function reLoadCore(uint256 _pID, uint256 _affID, uint256 _team, uint256 _eth, F3Ddatasets.EventReturns memory _eventData_) + private + { + // setup local rID + uint256 _rID = rID_; + + // grab time + uint256 _now = now; + + // if round is active + if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) + { + // get earnings from all vaults and return unused to gen vault + // because we use a custom safemath library. this will throw if player + // tried to spend more eth than they have. + plyr_[_pID].gen = withdrawEarnings(_pID).sub(_eth); + + // call core + core(_rID, _pID, _eth, _affID, _team, _eventData_); + + // if round is not active and end round needs to be ran + } else if (_now > round_[_rID].end && round_[_rID].ended == false) { + // end the round (distributes pot) & start new round + round_[_rID].ended = true; + _eventData_ = endRound(_eventData_); + + // build event data + _eventData_.compressedData = _eventData_.compressedData + (_now * 1000000000000000000); + _eventData_.compressedIDs = _eventData_.compressedIDs + _pID; + + // fire buy and distribute event + emit F3Devents.onReLoadAndDistribute + ( + msg.sender, + plyr_[_pID].name, + _eventData_.compressedData, + _eventData_.compressedIDs, + _eventData_.winnerAddr, + _eventData_.winnerName, + _eventData_.amountWon, + _eventData_.newPot, + _eventData_.P3DAmount, + _eventData_.genAmount + ); + } + } + + /** + * @dev this is the core logic for any buy/reload that happens while a round + * is live. + */ + function core(uint256 _rID, uint256 _pID, uint256 _eth, uint256 _affID, uint256 _team, F3Ddatasets.EventReturns memory _eventData_) + private + { + // if player is new to round + if (plyrRnds_[_pID][_rID].keys == 0) + _eventData_ = managePlayer(_pID, _eventData_); + + // early round eth limiter + if (round_[_rID].eth < 100000000000000000000 && plyrRnds_[_pID][_rID].eth.add(_eth) > 1000000000000000000) + { + uint256 _availableLimit = (1000000000000000000).sub(plyrRnds_[_pID][_rID].eth); + uint256 _refund = _eth.sub(_availableLimit); + plyr_[_pID].gen = plyr_[_pID].gen.add(_refund); + _eth = _availableLimit; + } + + // if eth left is greater than min eth allowed (sorry no pocket lint) + if (_eth > 1000000000) + { + + // mint the new keys + uint256 _keys = (round_[_rID].eth).keysRec(_eth); + + // if they bought at least 1 whole key + if (_keys >= 1000000000000000000) + { + updateTimer(_keys, _rID); + + // set new leaders + if (round_[_rID].plyr != _pID) + round_[_rID].plyr = _pID; + if (round_[_rID].team != _team) + round_[_rID].team = _team; + + // set the new leader bool to true + _eventData_.compressedData = _eventData_.compressedData + 100; + } + + // manage airdrops + if (_eth >= 100000000000000000) + { + airDropTracker_++; + if (airdrop() == true) + { + // gib muni + uint256 _prize; + if (_eth >= 10000000000000000000) + { + // calculate prize and give it to winner + _prize = ((airDropPot_).mul(75)) / 100; + plyr_[_pID].win = (plyr_[_pID].win).add(_prize); + + // adjust airDropPot + airDropPot_ = (airDropPot_).sub(_prize); + + // let event know a tier 3 prize was won + _eventData_.compressedData += 300000000000000000000000000000000; + } else if (_eth >= 1000000000000000000 && _eth < 10000000000000000000) { + // calculate prize and give it to winner + _prize = ((airDropPot_).mul(50)) / 100; + plyr_[_pID].win = (plyr_[_pID].win).add(_prize); + + // adjust airDropPot + airDropPot_ = (airDropPot_).sub(_prize); + + // let event know a tier 2 prize was won + _eventData_.compressedData += 200000000000000000000000000000000; + } else if (_eth >= 100000000000000000 && _eth < 1000000000000000000) { + // calculate prize and give it to winner + _prize = ((airDropPot_).mul(25)) / 100; + plyr_[_pID].win = (plyr_[_pID].win).add(_prize); + + // adjust airDropPot + airDropPot_ = (airDropPot_).sub(_prize); + + // let event know a tier 3 prize was won + _eventData_.compressedData += 300000000000000000000000000000000; + } + // set airdrop happened bool to true + _eventData_.compressedData += 10000000000000000000000000000000; + // let event know how much was won + _eventData_.compressedData += _prize * 1000000000000000000000000000000000; + + // reset air drop tracker + airDropTracker_ = 0; + } + } + + // store the air drop tracker number (number of buys since last airdrop) + _eventData_.compressedData = _eventData_.compressedData + (airDropTracker_ * 1000); + + // update player + plyrRnds_[_pID][_rID].keys = _keys.add(plyrRnds_[_pID][_rID].keys); + plyrRnds_[_pID][_rID].eth = _eth.add(plyrRnds_[_pID][_rID].eth); + + // update round + round_[_rID].keys = _keys.add(round_[_rID].keys); + round_[_rID].eth = _eth.add(round_[_rID].eth); + rndTmEth_[_rID][_team] = _eth.add(rndTmEth_[_rID][_team]); + + // distribute eth + _eventData_ = distributeExternal(_rID, _pID, _eth, _affID, _team, _eventData_); + _eventData_ = distributeInternal(_rID, _pID, _eth, _team, _keys, _eventData_); + + // call end tx function to fire end tx event. + endTx(_pID, _team, _eth, _keys, _eventData_); + } + } + //============================================================================== + // _ _ | _ | _ _|_ _ _ _ . + // (_(_||(_|_||(_| | (_)| _\ . + //============================================================================== + /** + * @dev calculates unmasked earnings (just calculates, does not update mask) + * @return earnings in wei format + */ + function calcUnMaskedEarnings(uint256 _pID, uint256 _rIDlast) + private + view + returns (uint256) + { + return ((((round_[_rIDlast].mask).mul(plyrRnds_[_pID][_rIDlast].keys)) / (1000000000000000000)).sub(plyrRnds_[_pID][_rIDlast].mask)); + } + + /** + * @dev returns the amount of keys you would get given an amount of eth. + * -functionhash- 0xce89c80c + * @param _rID round ID you want price for + * @param _eth amount of eth sent in + * @return keys received + */ + function calcKeysReceived(uint256 _rID, uint256 _eth) + public + view + returns (uint256) + { + // grab time + uint256 _now = now; + + // are we in a round? + if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) + return ((round_[_rID].eth).keysRec(_eth)); + else // rounds over. need keys for new round + return ((_eth).keys()); + } + + /** + * @dev returns current eth price for X keys. + * -functionhash- 0xcf808000 + * @param _keys number of keys desired (in 18 decimal format) + * @return amount of eth needed to send + */ + function iWantXKeys(uint256 _keys) + public + view + returns (uint256) + { + // setup local rID + uint256 _rID = rID_; + + // grab time + uint256 _now = now; + + // are we in a round? + if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) + return ((round_[_rID].keys.add(_keys)).ethRec(_keys)); + else // rounds over. need price for new round + return ((_keys).eth()); + } + //============================================================================== + // _|_ _ _ | _ . + // | (_)(_)|_\ . + //============================================================================== + /** + * @dev receives name/player info from names contract + */ + function receivePlayerInfo(uint256 _pID, address payable _addr, bytes32 _name, uint256 _laff) + external + { + require(msg.sender == address(playerBook), "your not playerNames contract... hmmm.."); + if (pIDxAddr_[_addr] != _pID) + pIDxAddr_[_addr] = _pID; + if (pIDxName_[_name] != _pID) + pIDxName_[_name] = _pID; + if (plyr_[_pID].addr != _addr) + plyr_[_pID].addr = _addr; + if (plyr_[_pID].name != _name) + plyr_[_pID].name = _name; + if (plyr_[_pID].laff != _laff) + plyr_[_pID].laff = _laff; + if (plyrNames_[_pID][_name] == false) + plyrNames_[_pID][_name] = true; + } + + /** + * @dev receives entire player name list + */ + function receivePlayerNameList(uint256 _pID, bytes32 _name) + external + { + require(msg.sender == address(playerBook), "your not playerNames contract... hmmm.."); + if (plyrNames_[_pID][_name] == false) + plyrNames_[_pID][_name] = true; + } + + /** + * @dev gets existing or registers new pID. use this when a player may be new + * @return pID + */ + function determinePID(F3Ddatasets.EventReturns memory _eventData_) + private + returns (F3Ddatasets.EventReturns memory) + { + uint256 _pID = pIDxAddr_[msg.sender]; + // if player is new to this version of fomo3d + if (_pID == 0) + { + // grab their player ID, name and last aff ID, from player names contract + _pID = playerBook.getPlayerID(msg.sender); + bytes32 _name = playerBook.getPlayerName(_pID); + uint256 _laff = playerBook.getPlayerLAff(_pID); + + // set up player account + pIDxAddr_[msg.sender] = _pID; + plyr_[_pID].addr = msg.sender; + + if (_name != "") + { + pIDxName_[_name] = _pID; + plyr_[_pID].name = _name; + plyrNames_[_pID][_name] = true; + } + + if (_laff != 0 && _laff != _pID) + plyr_[_pID].laff = _laff; + + // set the new player bool to true + _eventData_.compressedData = _eventData_.compressedData + 1; + } + return (_eventData_); + } + + /** + * @dev checks to make sure user picked a valid team. if not sets team + * to default (sneks) + */ + function verifyTeam(uint256 _team) + private + pure + returns (uint256) + { + if (_team < 0 || _team > 3) + return (2); + else + return (_team); + } + + /** + * @dev decides if round end needs to be run & new round started. and if + * player unmasked earnings from previously played rounds need to be moved. + */ + function managePlayer(uint256 _pID, F3Ddatasets.EventReturns memory _eventData_) + private + returns (F3Ddatasets.EventReturns memory) + { + // if player has played a previous round, move their unmasked earnings + // from that round to gen vault. + if (plyr_[_pID].lrnd != 0) + updateGenVault(_pID, plyr_[_pID].lrnd); + + // update player's last round played + plyr_[_pID].lrnd = rID_; + + // set the joined round bool to true + _eventData_.compressedData = _eventData_.compressedData + 10; + + return (_eventData_); + } + + /** + * @dev ends the round. manages paying out winner/splitting up pot + */ + function endRound(F3Ddatasets.EventReturns memory _eventData_) + private + returns (F3Ddatasets.EventReturns memory) + { + // setup local rID + uint256 _rID = rID_; + + // grab our winning player and team id's + uint256 _winPID = round_[_rID].plyr; + uint256 _winTID = round_[_rID].team; + + // grab our pot amount + uint256 _pot = round_[_rID].pot; + + // calculate our winner share, community rewards, gen share, + // p3d share, and amount reserved for next pot + uint256 _win = (_pot.mul(48)) / 100; + uint256 _com = (_pot / 50); + uint256 _gen = (_pot.mul(potSplit_[_winTID].gen)) / 100; + uint256 _p3d = (_pot.mul(potSplit_[_winTID].p3d)) / 100; + uint256 _res = (((_pot.sub(_win)).sub(_com)).sub(_gen)).sub(_p3d); + + // calculate ppt for round mask + uint256 _ppt = (_gen.mul(1000000000000000000)) / (round_[_rID].keys); + uint256 _dust = _gen.sub((_ppt.mul(round_[_rID].keys)) / 1000000000000000000); + if (_dust > 0) + { + _gen = _gen.sub(_dust); + _res = _res.add(_dust); + } + + // pay our winner + plyr_[_winPID].win = _win.add(plyr_[_winPID].win); + + // community rewards + address payable add = address(uint160(Jekyll_Island_Inc)); + if (!add.send(_com)) + { + // This ensures Team Just cannot influence the outcome of FoMo3D with + // bank migrations by breaking outgoing transactions. + // Something we would never do. But that's not the point. + // We spent 2000$ in eth re-deploying just to patch this, we hold the + // highest belief that everything we create should be trustless. + // Team JUST, The name you shouldn't have to trust. + _p3d = _p3d.add(_com); + _com = 0; + } + + // distribute gen portion to key holders + round_[_rID].mask = _ppt.add(round_[_rID].mask); + + // send share for p3d to divies + if (_p3d > 0){ + address payable addr = address(uint160(Divies)); + addr.transfer(_p3d); + } + // prepare event data + _eventData_.compressedData = _eventData_.compressedData + (round_[_rID].end * 1000000); + _eventData_.compressedIDs = _eventData_.compressedIDs + (_winPID * 100000000000000000000000000) + (_winTID * 100000000000000000); + _eventData_.winnerAddr = plyr_[_winPID].addr; + _eventData_.winnerName = plyr_[_winPID].name; + _eventData_.amountWon = _win; + _eventData_.genAmount = _gen; + _eventData_.P3DAmount = _p3d; + _eventData_.newPot = _res; + + // start next round + rID_++; + _rID++; + round_[_rID].strt = now; + round_[_rID].end = now.add(rndInit_).add(rndGap_); + round_[_rID].pot = _res; + + return (_eventData_); + } + + /** + * @dev moves any unmasked earnings to gen vault. updates earnings mask + */ + function updateGenVault(uint256 _pID, uint256 _rIDlast) + private + { + uint256 _earnings = calcUnMaskedEarnings(_pID, _rIDlast); + if (_earnings > 0) + { + // put in gen vault + plyr_[_pID].gen = _earnings.add(plyr_[_pID].gen); + // zero out their earnings by updating mask + plyrRnds_[_pID][_rIDlast].mask = _earnings.add(plyrRnds_[_pID][_rIDlast].mask); + } + } + + /** + * @dev updates round timer based on number of whole keys bought. + */ + function updateTimer(uint256 _keys, uint256 _rID) + private + { + // grab time + uint256 _now = now; + + // calculate time based on number of keys bought + uint256 _newTime; + if (_now > round_[_rID].end && round_[_rID].plyr == 0) + _newTime = (((_keys) / (1000000000000000000)).mul(rndInc_)).add(_now); + else + _newTime = (((_keys) / (1000000000000000000)).mul(rndInc_)).add(round_[_rID].end); + + // compare to max and set new end time + if (_newTime < (rndMax_).add(_now)) + round_[_rID].end = _newTime; + else + round_[_rID].end = rndMax_.add(_now); + } + + /** + * @dev generates a random number between 0-99 and checks to see if thats + * resulted in an airdrop win + * @return do we have a winner? + */ + function airdrop() + private + view + returns (bool) + { + uint256 seed = uint256(keccak256(abi.encodePacked( + + (block.timestamp).add + (block.difficulty).add + ((uint256(keccak256(abi.encodePacked(block.coinbase)))) / (now)).add + (block.gaslimit).add + ((uint256(keccak256(abi.encodePacked(msg.sender)))) / (now)).add + (block.number) + + ))); + if ((seed - ((seed / 1000) * 1000)) < airDropTracker_) + return (true); + else + return (false); + } + + /** + * @dev distributes eth based on fees to com, aff, and p3d + */ + function distributeExternal(uint256 _rID, uint256 _pID, uint256 _eth, uint256 _affID, uint256 _team, F3Ddatasets.EventReturns memory _eventData_) + private + returns (F3Ddatasets.EventReturns memory) + { + // pay 2% out to community rewards + uint256 _com = _eth / 50; + uint256 _p3d; + address payable addr = address(uint160(Jekyll_Island_Inc)); + if (!addr.send(_com)) + { + // This ensures Team Just cannot influence the outcome of FoMo3D with + // bank migrations by breaking outgoing transactions. + // Something we would never do. But that's not the point. + // We spent 2000$ in eth re-deploying just to patch this, we hold the + // highest belief that everything we create should be trustless. + // Team JUST, The name you shouldn't have to trust. + _p3d = _com; + _com = 0; + } + + // pay 1% out to FoMo3D short + _com = _eth / 100; + address payable add = address(uint160(otherF3D_)); + add.transfer(_com); + + // distribute share to affiliate + _com = _eth / 10; + + // decide what to do with affiliate share of fees + // affiliate must not be self, and must have a name registered + if (_affID != _pID && plyr_[_affID].name != '') { + plyr_[_affID].aff = _com.add(plyr_[_affID].aff); + emit F3Devents.onAffiliatePayout(_affID, plyr_[_affID].addr, plyr_[_affID].name, _rID, _pID, _com, now); + } else { + _p3d = _com; + } + + // pay out p3d + _p3d = _p3d.add((_eth.mul(fees_[_team].p3d)) / (100)); + if (_p3d > 0) + { + // deposit to divies contract + address payable add = address(uint160(Divies)); + add.transfer(_p3d); + + // set up event data + _eventData_.P3DAmount = _p3d.add(_eventData_.P3DAmount); + } + + return (_eventData_); + } + + function potSwap() + external + payable + { + // setup local rID + uint256 _rID = rID_ + 1; + + round_[_rID].pot = round_[_rID].pot.add(msg.value); + emit F3Devents.onPotSwapDeposit(_rID, msg.value); + } + + /** + * @dev distributes eth based on fees to gen and pot + */ + function distributeInternal(uint256 _rID, uint256 _pID, uint256 _eth, uint256 _team, uint256 _keys, F3Ddatasets.EventReturns memory _eventData_) + private + returns (F3Ddatasets.EventReturns memory) + { + // calculate gen share + uint256 _gen = (_eth.mul(fees_[_team].gen)) / 100; + + // toss 1% into airdrop pot + uint256 _air = (_eth / 100); + airDropPot_ = airDropPot_.add(_air); + + // update eth balance (eth = eth - (com share + pot swap share + aff share + p3d share + airdrop pot share)) + _eth = _eth.sub(((_eth.mul(14)) / 100).add((_eth.mul(fees_[_team].p3d)) / 100)); + + // calculate pot + uint256 _pot = _eth.sub(_gen); + + // distribute gen share (thats what updateMasks() does) and adjust + // balances for dust. + uint256 _dust = updateMasks(_rID, _pID, _gen, _keys); + if (_dust > 0) + _gen = _gen.sub(_dust); + + // add eth to pot + round_[_rID].pot = _pot.add(_dust).add(round_[_rID].pot); + + // set up event data + _eventData_.genAmount = _gen.add(_eventData_.genAmount); + _eventData_.potAmount = _pot; + + return (_eventData_); + } + + /** + * @dev updates masks for round and player when keys are bought + * @return dust left over + */ + function updateMasks(uint256 _rID, uint256 _pID, uint256 _gen, uint256 _keys) + private + returns (uint256) + { + /* MASKING NOTES + earnings masks are a tricky thing for people to wrap their minds around. + the basic thing to understand here. is were going to have a global + tracker based on profit per share for each round, that increases in + relevant proportion to the increase in share supply. + + the player will have an additional mask that basically says "based + on the rounds mask, my shares, and how much i've already withdrawn, + how much is still owed to me?" + */ + + // calc profit per key & round mask based on this buy: (dust goes to pot) + uint256 _ppt = (_gen.mul(1000000000000000000)) / (round_[_rID].keys); + round_[_rID].mask = _ppt.add(round_[_rID].mask); + + // calculate player earning from their own buy (only based on the keys + // they just bought). & update player earnings mask + uint256 _pearn = (_ppt.mul(_keys)) / (1000000000000000000); + plyrRnds_[_pID][_rID].mask = (((round_[_rID].mask.mul(_keys)) / (1000000000000000000)).sub(_pearn)).add(plyrRnds_[_pID][_rID].mask); + + // calculate & return dust + return (_gen.sub((_ppt.mul(round_[_rID].keys)) / (1000000000000000000))); + } + + /** + * @dev adds up unmasked earnings, & vault earnings, sets them all to 0 + * @return earnings in wei format + */ + function withdrawEarnings(uint256 _pID) + private + returns (uint256) + { + // update gen vault + updateGenVault(_pID, plyr_[_pID].lrnd); + + // from vaults + uint256 _earnings = (plyr_[_pID].win).add(plyr_[_pID].gen).add(plyr_[_pID].aff); + if (_earnings > 0) + { + plyr_[_pID].win = 0; + plyr_[_pID].gen = 0; + plyr_[_pID].aff = 0; + } + + return (_earnings); + } + + /** + * @dev prepares compression data and fires event for buy or reload tx's + */ + function endTx(uint256 _pID, uint256 _team, uint256 _eth, uint256 _keys, F3Ddatasets.EventReturns memory _eventData_) + private + { + _eventData_.compressedData = _eventData_.compressedData + (now * 1000000000000000000) + (_team * 100000000000000000000000000000); + _eventData_.compressedIDs = _eventData_.compressedIDs + _pID + (rID_ * 10000000000000000000000000000000000000000000000000000); + + emit F3Devents.onEndTx + ( + _eventData_.compressedData, + _eventData_.compressedIDs, + plyr_[_pID].name, + msg.sender, + _eth, + _keys, + _eventData_.winnerAddr, + _eventData_.winnerName, + _eventData_.amountWon, + _eventData_.newPot, + _eventData_.P3DAmount, + _eventData_.genAmount, + _eventData_.potAmount, + airDropPot_ + ); + } + //============================================================================== + // (~ _ _ _._|_ . + // _)(/_(_|_|| | | \/ . + //====================/========================================================= + /** upon contract deploy, it will be deactivated. this is a one time + * use function that will activate the contract. we do this so devs + * have time to set things up on the web end **/ + bool public activated_ = false; + + function activate() + public + onlyDevs + { + + // can only be ran once + require(activated_ == false, "fomo3d already activated"); + + // activate the contract + activated_ = true; + + otherF3D_ = msg.sender; + Divies = msg.sender; + Jekyll_Island_Inc = msg.sender; + + // lets start first round + rID_ = 1; + round_[1].strt = now + rndExtra_ - rndGap_; + round_[1].end = now + rndInit_ + rndExtra_; + } + + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractScenario007.sol b/src/test/resources/soliditycode/contractScenario007.sol new file mode 100644 index 00000000000..b3d1313c3e4 --- /dev/null +++ b/src/test/resources/soliditycode/contractScenario007.sol @@ -0,0 +1,1433 @@ +//pragma solidity 0.4.24; + +/** + * @title ERC165 + * @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md + */ +interface ERC165 { + + /** + * @notice Query if a contract implements an interface + * @param _interfaceId The interface identifier, as specified in ERC-165 + * @dev Interface identification is specified in ERC-165. This function + * uses less than 30,000 gas. + */ + function supportsInterface(bytes4 _interfaceId) external view returns (bool); + +} + +contract ERC721Basic is ERC165 { + + event Transfer( + address indexed _from, + address indexed _to, + uint256 indexed _tokenId + ); + event Approval( + address indexed _owner, + address indexed _approved, + uint256 indexed _tokenId + ); + event ApprovalForAll( + address indexed _owner, + address indexed _operator, + bool _approved + ); + + function balanceOf(address _owner) public view returns (uint256 _balance); + function ownerOf(uint256 _tokenId) public view returns (address _owner); + function exists(uint256 _tokenId) public view returns (bool _exists); + + function approve(address _to, uint256 _tokenId) public; + function getApproved(uint256 _tokenId) + public view returns (address _operator); + + function setApprovalForAll(address _operator, bool _approved) public; + function isApprovedForAll(address _owner, address _operator) + public view returns (bool); + + function transferFrom(address _from, address _to, uint256 _tokenId) public; + function safeTransferFrom(address _from, address _to, uint256 _tokenId) + public; + + function safeTransferFrom( + address _from, + address _to, + uint256 _tokenId, + bytes memory _data + ) + public; +} + + +/** + * @title SupportsInterfaceWithLookup + * @author Matt Condon (@shrugs) + * @dev Implements ERC165 using a lookup table. + */ +contract SupportsInterfaceWithLookup is ERC165 { + bytes4 public constant InterfaceId_ERC165 = 0x01ffc9a7; + /** + * 0x01ffc9a7 === + * bytes4(keccak256('supportsInterface(bytes4)')) + */ + + /** + * @dev a mapping of interface id to whether or not it's supported + */ + mapping(bytes4 => bool) internal supportedInterfaces; + + /** + * @dev A contract implementing SupportsInterfaceWithLookup + * implement ERC165 itself + */ + constructor() public { + _registerInterface(InterfaceId_ERC165); + } + + /** + * @dev implement supportsInterface(bytes4) using a lookup table + */ + function supportsInterface(bytes4 _interfaceId) external view returns (bool) { + return supportedInterfaces[_interfaceId]; + } + + /** + * @dev private method for registering an interface + */ + function _registerInterface(bytes4 _interfaceId) internal { + require(_interfaceId != 0xffffffff); + supportedInterfaces[_interfaceId] = true; + } +} + +contract Governable { + + event Pause(); + event Unpause(); + + address public governor; + bool public paused = false; + + constructor() public { + governor = msg.sender; + } + + function setGovernor(address _gov) public onlyGovernor { + governor = _gov; + } + + modifier onlyGovernor { + require(msg.sender == governor); + _; + } + + /** + * @dev Modifier to make a function callable only when the contract is not paused. + */ + modifier whenNotPaused() { + require(!paused); + _; + } + + /** + * @dev Modifier to make a function callable only when the contract is paused. + */ + modifier whenPaused() { + require(paused); + _; + } + + /** + * @dev called by the owner to pause, triggers stopped state + */ + function pause() onlyGovernor whenNotPaused public { + paused = true; + emit Pause(); + } + + /** + * @dev called by the owner to unpause, returns to normal state + */ + function unpause() onlyGovernor whenPaused public { + paused = false; + emit Unpause(); + } + +} + +contract CardBase is Governable { + + struct Card { + uint16 proto; + uint16 purity; + } + + function getCard(uint id) public view returns (uint16 proto, uint16 purity) { + Card memory card = cards[id]; + return (card.proto, card.purity); + } + + function getShine(uint16 purity) public pure returns (uint8) { + return uint8(purity / 1000); + } + + Card[] public cards; + +} + +contract CardProto is CardBase { + + event NewProtoCard( + uint16 id, uint8 season, uint8 god, + Rarity rarity, uint8 mana, uint8 attack, + uint8 health, uint8 cardType, uint8 tribe, bool packable + ); + + struct Limit { + uint64 limit; + bool exists; + } + + // limits for mythic cards + mapping(uint16 => Limit) public limits; + + // can only set limits once + function setLimit(uint16 id, uint64 limit) public onlyGovernor { + Limit memory l = limits[id]; + require(!l.exists); + limits[id] = Limit({ + limit: limit, + exists: true + }); + } + + function getLimit(uint16 id) public view returns (uint64 limit, bool set) { + Limit memory l = limits[id]; + return (l.limit, l.exists); + } + + // could make these arrays to save gas + // not really necessary - will be update a very limited no of times + mapping(uint8 => bool) public seasonTradable; + mapping(uint8 => bool) public seasonTradabilityLocked; + uint8 public currentSeason; + + function makeTradable(uint8 season) public onlyGovernor { + seasonTradable[season] = true; + } + + function makeUntradable(uint8 season) public onlyGovernor { + require(!seasonTradabilityLocked[season]); + seasonTradable[season] = false; + } + + function makePermanantlyTradable(uint8 season) public onlyGovernor { + require(seasonTradable[season]); + seasonTradabilityLocked[season] = true; + } + + function isTradable(uint16 proto) public view returns (bool) { + return seasonTradable[protos[proto].season]; + } + + function nextSeason() public onlyGovernor { + //Seasons shouldn't go to 0 if there is more than the uint8 should hold, the governor should know this ¯\_(ツ)_/¯ -M + require(currentSeason <= 255); + + currentSeason++; + mythic.length = 0; + legendary.length = 0; + epic.length = 0; + rare.length = 0; + common.length = 0; + } + + enum Rarity { + Common, + Rare, + Epic, + Legendary, + Mythic + } + + uint8 constant SPELL = 1; + uint8 constant MINION = 2; + uint8 constant WEAPON = 3; + uint8 constant HERO = 4; + + struct ProtoCard { + bool exists; + uint8 god; + uint8 season; + uint8 cardType; + Rarity rarity; + uint8 mana; + uint8 attack; + uint8 health; + uint8 tribe; + } + + // there is a particular design decision driving this: + // need to be able to iterate over mythics only for card generation + // don't store 5 different arrays: have to use 2 ids + // better to bear this cost (2 bytes per proto card) + // rather than 1 byte per instance + + uint16 public protoCount; + + mapping(uint16 => ProtoCard) protos; + + uint16[] public mythic; + uint16[] public legendary; + uint16[] public epic; + uint16[] public rare; + uint16[] public common; + + function addProtos( + uint16[] memory externalIDs, uint8[] memory gods, Rarity[] memory rarities, uint8[] memory manas, uint8[] memory attacks, + uint8[] memory healths, uint8[] memory cardTypes, uint8[] memory tribes, bool[] memory packable + ) public onlyGovernor returns(uint16) { + + for (uint i = 0; i < externalIDs.length; i++) { + + ProtoCard memory card = ProtoCard({ + exists: true, + god: gods[i], + season: currentSeason, + cardType: cardTypes[i], + rarity: rarities[i], + mana: manas[i], + attack: attacks[i], + health: healths[i], + tribe: tribes[i] + }); + + _addProto(externalIDs[i], card, packable[i]); + } + + } + + function addProto( + uint16 externalID, uint8 god, Rarity rarity, uint8 mana, uint8 attack, uint8 health, uint8 cardType, uint8 tribe, bool packable + ) public onlyGovernor returns(uint16) { + ProtoCard memory card = ProtoCard({ + exists: true, + god: god, + season: currentSeason, + cardType: cardType, + rarity: rarity, + mana: mana, + attack: attack, + health: health, + tribe: tribe + }); + + _addProto(externalID, card, packable); + } + + function addWeapon( + uint16 externalID, uint8 god, Rarity rarity, uint8 mana, uint8 attack, uint8 durability, bool packable + ) public onlyGovernor returns(uint16) { + + ProtoCard memory card = ProtoCard({ + exists: true, + god: god, + season: currentSeason, + cardType: WEAPON, + rarity: rarity, + mana: mana, + attack: attack, + health: durability, + tribe: 0 + }); + + _addProto(externalID, card, packable); + } + + function addSpell(uint16 externalID, uint8 god, Rarity rarity, uint8 mana, bool packable) public onlyGovernor returns(uint16) { + + ProtoCard memory card = ProtoCard({ + exists: true, + god: god, + season: currentSeason, + cardType: SPELL, + rarity: rarity, + mana: mana, + attack: 0, + health: 0, + tribe: 0 + }); + + _addProto(externalID, card, packable); + } + + function addMinion( + uint16 externalID, uint8 god, Rarity rarity, uint8 mana, uint8 attack, uint8 health, uint8 tribe, bool packable + ) public onlyGovernor returns(uint16) { + + ProtoCard memory card = ProtoCard({ + exists: true, + god: god, + season: currentSeason, + cardType: MINION, + rarity: rarity, + mana: mana, + attack: attack, + health: health, + tribe: tribe + }); + + _addProto(externalID, card, packable); + } + + function _addProto(uint16 externalID, ProtoCard memory card, bool packable) internal { + + require(!protos[externalID].exists); + + card.exists = true; + + protos[externalID] = card; + + protoCount++; + + emit NewProtoCard( + externalID, currentSeason, card.god, + card.rarity, card.mana, card.attack, + card.health, card.cardType, card.tribe, packable + ); + + if (packable) { + Rarity rarity = card.rarity; + if (rarity == Rarity.Common) { + common.push(externalID); + } else if (rarity == Rarity.Rare) { + rare.push(externalID); + } else if (rarity == Rarity.Epic) { + epic.push(externalID); + } else if (rarity == Rarity.Legendary) { + legendary.push(externalID); + } else if (rarity == Rarity.Mythic) { + mythic.push(externalID); + } else { + require(false); + } + } + } + + function getProto(uint16 id) public view returns( + bool exists, uint8 god, uint8 season, uint8 cardType, Rarity rarity, uint8 mana, uint8 attack, uint8 health, uint8 tribe + ) { + ProtoCard memory proto = protos[id]; + return ( + proto.exists, + proto.god, + proto.season, + proto.cardType, + proto.rarity, + proto.mana, + proto.attack, + proto.health, + proto.tribe + ); + } + + function getRandomCard(Rarity rarity, uint16 random) public view returns (uint16) { + // modulo bias is fine - creates rarity tiers etc + // will obviously revert is there are no cards of that type: this is expected - should never happen + if (rarity == Rarity.Common) { + return common[random % common.length]; + } else if (rarity == Rarity.Rare) { + return rare[random % rare.length]; + } else if (rarity == Rarity.Epic) { + return epic[random % epic.length]; + } else if (rarity == Rarity.Legendary) { + return legendary[random % legendary.length]; + } else if (rarity == Rarity.Mythic) { + // make sure a mythic is available + uint16 id; + uint64 limit; + bool set; + for (uint i = 0; i < mythic.length; i++) { + id = mythic[(random + i) % mythic.length]; + (limit, set) = getLimit(id); + if (set && limit > 0){ + return id; + } + } + // if not, they get a legendary :( + return legendary[random % legendary.length]; + } + require(false); + return 0; + } + + // can never adjust tradable cards + // each season gets a 'balancing beta' + // totally immutable: season, rarity + function replaceProto( + uint16 index, uint8 god, uint8 cardType, uint8 mana, uint8 attack, uint8 health, uint8 tribe + ) public onlyGovernor { + ProtoCard memory pc = protos[index]; + require(!seasonTradable[pc.season]); + protos[index] = ProtoCard({ + exists: true, + god: god, + season: pc.season, + cardType: cardType, + rarity: pc.rarity, + mana: mana, + attack: attack, + health: health, + tribe: tribe + }); + } + +} + +contract ERC721Receiver { + /** + * @dev Magic value to be returned upon successful reception of an NFT + * Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`, + * which can be also obtained as `ERC721Receiver(0).onERC721Received.selector` + */ + bytes4 internal constant ERC721_RECEIVED = 0x150b7a02; + + /** + * @notice Handle the receipt of an NFT + * @dev The ERC721 smart contract calls this function on the recipient + * after a `safetransfer`. This function MAY throw to revert and reject the + * transfer. Return of other than the magic value MUST result in the + * transaction being reverted. + * Note: the contract address is always the message sender. + * @param _operator The address which called `safeTransferFrom` function + * @param _from The address which previously owned the token + * @param _tokenId The NFT identifier which is being transfered + * @param _data Additional data with no specified format + * @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` + */ + function onERC721Received( + address _operator, + address _from, + uint256 _tokenId, + bytes memory _data + ) + public + returns(bytes4); +} + +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; + } + +} + +library SafeMath { + + /** + * @dev Multiplies two numbers, throws on overflow. + */ + function mul(uint256 a, uint256 b) internal pure returns (uint256 c) { + // Gas optimization: this is cheaper than asserting 'a' not being zero, but the + // benefit is lost if 'b' is also tested. + // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 + if (a == 0) { + return 0; + } + + c = a * b; + assert(c / a == b); + return c; + } + + /** + * @dev Integer division of two numbers, truncating the quotient. + */ + function div(uint256 a, uint256 b) internal pure returns (uint256) { + // assert(b > 0); // Solidity automatically throws when dividing by 0 + // uint256 c = a / b; + // assert(a == b * c + a % b); // There is no case in which this doesn't hold + return a / b; + } + + /** + * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). + */ + function sub(uint256 a, uint256 b) internal pure returns (uint256) { + assert(b <= a); + return a - b; + } + + /** + * @dev Adds two numbers, throws on overflow. + */ + function add(uint256 a, uint256 b) internal pure returns (uint256 c) { + c = a + b; + assert(c >= a); + return c; + } +} + +contract ERC721BasicToken is CardProto, SupportsInterfaceWithLookup, ERC721Basic { + + bytes4 private constant InterfaceId_ERC721 = 0x80ac58cd; + /* + * 0x80ac58cd === + * bytes4(keccak256('balanceOf(address)')) ^ + * bytes4(keccak256('ownerOf(uint256)')) ^ + * bytes4(keccak256('approve(address,uint256)')) ^ + * bytes4(keccak256('getApproved(uint256)')) ^ + * bytes4(keccak256('setApprovalForAll(address,bool)')) ^ + * bytes4(keccak256('isApprovedForAll(address,address)')) ^ + * bytes4(keccak256('transferFrom(address,address,uint256)')) ^ + * bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^ + * bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) + */ + + bytes4 private constant InterfaceId_ERC721Exists = 0x4f558e79; + /* + * 0x4f558e79 === + * bytes4(keccak256('exists(uint256)')) + */ + + using SafeMath for uint256; + using AddressUtils for address; + + // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` + // which can be also obtained as `ERC721Receiver(0).onERC721Received.selector` + bytes4 private constant ERC721_RECEIVED = 0x150b7a02; + + // Mapping from token ID to owner + mapping (uint256 => address) internal tokenOwner; + + // Mapping from token ID to approved address + mapping (uint256 => address) internal tokenApprovals; + + // Mapping from owner to number of owned token + // mapping (address => uint256) internal ownedTokensCount; + + // Mapping from owner to operator approvals + mapping (address => mapping (address => bool)) internal operatorApprovals; + + /** + * @dev Guarantees msg.sender is owner of the given token + * @param _tokenId uint256 ID of the token to validate its ownership belongs to msg.sender + */ + modifier onlyOwnerOf(uint256 _tokenId) { + require(ownerOf(_tokenId) == msg.sender); + _; + } + + /** + * @dev Checks msg.sender can transfer a token, by being owner, approved, or operator + * @param _tokenId uint256 ID of the token to validate + */ + modifier canTransfer(uint256 _tokenId) { + require(isApprovedOrOwner(msg.sender, _tokenId)); + _; + } + + constructor() + public + { + // register the supported interfaces to conform to ERC721 via ERC165 + _registerInterface(InterfaceId_ERC721); + _registerInterface(InterfaceId_ERC721Exists); + } + + /** + * @dev Gets the balance of the specified address + * @param _owner address to query the balance of + * @return uint256 representing the amount owned by the passed address + */ + function balanceOf(address _owner) public view returns (uint256); + + /** + * @dev Gets the owner of the specified token ID + * @param _tokenId uint256 ID of the token to query the owner of + * @return owner address currently marked as the owner of the given token ID + */ + function ownerOf(uint256 _tokenId) public view returns (address) { + address owner = tokenOwner[_tokenId]; + require(owner != address(0)); + return owner; + } + + /** + * @dev Returns whether the specified token exists + * @param _tokenId uint256 ID of the token to query the existence of + * @return whether the token exists + */ + function exists(uint256 _tokenId) public view returns (bool) { + address owner = tokenOwner[_tokenId]; + return owner != address(0); + } + + /** + * @dev Approves another address to transfer the given token ID + * The zero address indicates there is no approved address. + * There can only be one approved address per token at a given time. + * Can only be called by the token owner or an approved operator. + * @param _to address to be approved for the given token ID + * @param _tokenId uint256 ID of the token to be approved + */ + function approve(address _to, uint256 _tokenId) public { + address owner = ownerOf(_tokenId); + require(_to != owner); + require(msg.sender == owner || isApprovedForAll(owner, msg.sender)); + + tokenApprovals[_tokenId] = _to; + emit Approval(owner, _to, _tokenId); + } + + /** + * @dev Gets the approved address for a token ID, or zero if no address set + * @param _tokenId uint256 ID of the token to query the approval of + * @return address currently approved for the given token ID + */ + function getApproved(uint256 _tokenId) public view returns (address) { + return tokenApprovals[_tokenId]; + } + + /** + * @dev Sets or unsets the approval of a given operator + * An operator is allowed to transfer all tokens of the sender on their behalf + * @param _to operator address to set the approval + * @param _approved representing the status of the approval to be set + */ + function setApprovalForAll(address _to, bool _approved) public { + require(_to != msg.sender); + operatorApprovals[msg.sender][_to] = _approved; + emit ApprovalForAll(msg.sender, _to, _approved); + } + + /** + * @dev Tells whether an operator is approved by a given owner + * @param _owner owner address which you want to query the approval of + * @param _operator operator address which you want to query the approval of + * @return bool whether the given operator is approved by the given owner + */ + function isApprovedForAll( + address _owner, + address _operator + ) + public + view + returns (bool) + { + return operatorApprovals[_owner][_operator]; + } + + /** + * @dev Transfers the ownership of a given token ID to another address + * Usage of this method is discouraged, use `safeTransferFrom` whenever possible + * Requires the msg sender to be the owner, approved, or operator + * @param _from current owner of the token + * @param _to address to receive the ownership of the given token ID + * @param _tokenId uint256 ID of the token to be transferred + */ + function transferFrom( + address _from, + address _to, + uint256 _tokenId + ) + public + canTransfer(_tokenId) + { + require(_from != address(0)); + require(_to != address(0)); + + clearApproval(_from, _tokenId); + removeTokenFrom(_from, _tokenId); + addTokenTo(_to, _tokenId); + + emit Transfer(_from, _to, _tokenId); + } + + /** + * @dev Safely transfers the ownership of a given token ID to another address + * If the target address is a contract, it must implement `onERC721Received`, + * which is called upon a safe transfer, and return the magic value + * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, + * the transfer is reverted. + * + * Requires the msg sender to be the owner, approved, or operator + * @param _from current owner of the token + * @param _to address to receive the ownership of the given token ID + * @param _tokenId uint256 ID of the token to be transferred + */ + function safeTransferFrom( + address _from, + address _to, + uint256 _tokenId + ) + public + canTransfer(_tokenId) + { + // solium-disable-next-line arg-overflow + safeTransferFrom(_from, _to, _tokenId, ""); + } + + /** + * @dev Safely transfers the ownership of a given token ID to another address + * If the target address is a contract, it must implement `onERC721Received`, + * which is called upon a safe transfer, and return the magic value + * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, + * the transfer is reverted. + * Requires the msg sender to be the owner, approved, or operator + * @param _from current owner of the token + * @param _to address to receive the ownership of the given token ID + * @param _tokenId uint256 ID of the token to be transferred + * @param _data bytes data to send along with a safe transfer check + */ + function safeTransferFrom( + address _from, + address _to, + uint256 _tokenId, + bytes memory _data + ) + public + canTransfer(_tokenId) + { + transferFrom(_from, _to, _tokenId); + // solium-disable-next-line arg-overflow + require(checkAndCallSafeTransfer(_from, _to, _tokenId, _data)); + } + + /** + * @dev Returns whether the given spender can transfer a given token ID + * @param _spender address of the spender to query + * @param _tokenId uint256 ID of the token to be transferred + * @return bool whether the msg.sender is approved for the given token ID, + * is an operator of the owner, or is the owner of the token + */ + function isApprovedOrOwner( + address _spender, + uint256 _tokenId + ) + internal + view + returns (bool) + { + address owner = ownerOf(_tokenId); + // Disable solium check because of + // https://github.com/duaraghav8/Solium/issues/175 + // solium-disable-next-line operator-whitespace + return ( + _spender == owner || + getApproved(_tokenId) == _spender || + isApprovedForAll(owner, _spender) + ); + } + + /** + * @dev Internal function to clear current approval of a given token ID + * Reverts if the given address is not indeed the owner of the token + * @param _owner owner of the token + * @param _tokenId uint256 ID of the token to be transferred + */ + function clearApproval(address _owner, uint256 _tokenId) internal { + require(ownerOf(_tokenId) == _owner); + if (tokenApprovals[_tokenId] != address(0)) { + tokenApprovals[_tokenId] = address(0); + } + } + + /** + * @dev Internal function to mint a new token + * Reverts if the given token ID already exists + * @param _to The address that will own the minted token + * @param _tokenId uint256 ID of the token to be minted by the msg.sender + */ + function _mint(address _to, uint256 _tokenId) internal { + require(_to != address(0)); + addNewTokenTo(_to, _tokenId); + emit Transfer(address(0), _to, _tokenId); + } + + + /** + * @dev Internal function to burn a specific token + * Reverts if the token does not exist + * @param _tokenId uint256 ID of the token being burned by the msg.sender + */ + function _burn(address _owner, uint256 _tokenId) internal { + clearApproval(_owner, _tokenId); + removeTokenFrom(_owner, _tokenId); + emit Transfer(_owner, address(0), _tokenId); + } + + function addNewTokenTo(address _to, uint256 _tokenId) internal { + require(tokenOwner[_tokenId] == address(0)); + tokenOwner[_tokenId] = _to; + } + + /** + * @dev Internal function to add a token ID to the list of a given address + * @param _to address representing the new owner of the given token ID + * @param _tokenId uint256 ID of the token to be added to the tokens list of the given address + */ + function addTokenTo(address _to, uint256 _tokenId) internal { + require(tokenOwner[_tokenId] == address(0)); + tokenOwner[_tokenId] = _to; + // ownedTokensCount[_to] = ownedTokensCount[_to].add(1); + } + + /** + * @dev Internal function to remove a token ID from the list of a given address + * @param _from address representing the previous owner of the given token ID + * @param _tokenId uint256 ID of the token to be removed from the tokens list of the given address + */ + function removeTokenFrom(address _from, uint256 _tokenId) internal { + require(ownerOf(_tokenId) == _from); + // ownedTokensCount[_from] = ownedTokensCount[_from].sub(1); + tokenOwner[_tokenId] = address(0); + } + + /** + * @dev Internal function to invoke `onERC721Received` on a target address + * The call is not executed if the target address is not a contract + * @param _from address representing the previous owner of the given token ID + * @param _to target address that will receive the tokens + * @param _tokenId uint256 ID of the token to be transferred + * @param _data bytes optional data to send along with the call + * @return whether the call correctly returned the expected magic value + */ + function checkAndCallSafeTransfer( + address _from, + address _to, + uint256 _tokenId, + bytes memory _data + ) + internal + returns (bool) + { + if (!_to.isContract()) { + return true; + } + bytes4 retval = ERC721Receiver(_to).onERC721Received( + msg.sender, _from, _tokenId, _data); + return (retval == ERC721_RECEIVED); + } + +} + + + +contract ERC721Enumerable is ERC721Basic { + function totalSupply() public view returns (uint256); + function tokenOfOwnerByIndex( + address _owner, + uint256 _index + ) + public + view + returns (uint256 _tokenId); + + function tokenByIndex(uint256 _index) public view returns (uint256); +} + +contract ERC721Metadata is ERC721Basic { + function name() external view returns (string memory _name); + function symbol() external view returns (string memory _symbol); + function tokenURI(uint256 _tokenId) public view returns (string memory); +} + +contract ERC721 is ERC721Basic, ERC721Enumerable, ERC721Metadata { + +} + + + + +library Strings { + + // via https://github.com/oraclize/ethereum-api/blob/master/oraclizeAPI_0.5.sol + function strConcat(string memory _a, string memory _b, string memory _c, string memory _d, string memory _e) internal pure returns (string memory ) { + bytes memory _ba = bytes(_a); + bytes memory _bb = bytes(_b); + bytes memory _bc = bytes(_c); + bytes memory _bd = bytes(_d); + bytes memory _be = bytes(_e); + string memory abcde = new string(_ba.length + _bb.length + _bc.length + _bd.length + _be.length); + bytes memory babcde = bytes(abcde); + uint k = 0; + for (uint i = 0; i < _ba.length; i++) babcde[k++] = _ba[i]; + for (uint i = 0; i < _bb.length; i++) babcde[k++] = _bb[i]; + for (uint i = 0; i < _bc.length; i++) babcde[k++] = _bc[i]; + for (uint i = 0; i < _bd.length; i++) babcde[k++] = _bd[i]; + for (uint i = 0; i < _be.length; i++) babcde[k++] = _be[i]; + return string(babcde); + } + + function strConcat(string memory _a, string memory _b, string memory _c, string memory _d) internal pure returns (string memory ) { + return strConcat(_a, _b, _c, _d, ""); + } + + function strConcat(string memory _a, string memory _b, string memory _c) internal pure returns (string memory ) { + return strConcat(_a, _b, _c, "", ""); + } + + function strConcat(string memory _a, string memory _b) internal pure returns (string memory ) { + return strConcat(_a, _b, "", "", ""); + } + + function uint2str(uint i) internal pure returns (string memory ) { + if (i == 0) return "0"; + uint j = i; + uint len; + while (j != 0){ + len++; + j /= 10; + } + bytes memory bstr = new bytes(len); + uint k = len - 1; + while (i != 0){ + bstr[k--] = byte(uint8(48 + i % 10)); + i /= 10; + } + return string(bstr); + } +} + +contract ERC721Token is SupportsInterfaceWithLookup, ERC721BasicToken, ERC721 { + + using Strings for string; + + bytes4 private constant InterfaceId_ERC721Enumerable = 0x780e9d63; + /** + * 0x780e9d63 === + * bytes4(keccak256('totalSupply()')) ^ + * bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) ^ + * bytes4(keccak256('tokenByIndex(uint256)')) + */ + + bytes4 private constant InterfaceId_ERC721Metadata = 0x5b5e139f; + /** + * 0x5b5e139f === + * bytes4(keccak256('name()')) ^ + * bytes4(keccak256('symbol()')) ^ + * bytes4(keccak256('tokenURI(uint256)')) + */ + + /*** Constants ***/ + // Configure these for your own deployment + string public constant NAME = "Gods Unchained"; + string public constant SYMBOL = "GODS"; + string public tokenMetadataBaseURI = "https://api.godsunchained.com/card/"; + + // Mapping from owner to list of owned token IDs + // EDITED: limit to 2^40 (around 1T) + mapping(address => uint40[]) internal ownedTokens; + + uint32[] ownedTokensIndex; + + /** + * @dev Constructor function + */ + constructor() public { + + // register the supported interfaces to conform to ERC721 via ERC165 + _registerInterface(InterfaceId_ERC721Enumerable); + _registerInterface(InterfaceId_ERC721Metadata); + } + + /** + * @dev Gets the token name + * @return string representing the token name + */ + function name() external view returns (string memory) { + return NAME; + } + + /** + * @dev Gets the token symbol + * @return string representing the token symbol + */ + function symbol() external view returns (string memory) { + return SYMBOL; + } + + /** + * @dev Returns an URI for a given token ID + * Throws if the token ID does not exist. May return an empty string. + * @param _tokenId uint256 ID of the token to query + */ + function tokenURI(uint256 _tokenId) public view returns (string memory) { + return Strings.strConcat( + tokenMetadataBaseURI, + Strings.uint2str(_tokenId) + ); + } + + /** + * @dev Gets the token ID at a given index of the tokens list of the requested owner + * @param _owner address owning the tokens list to be accessed + * @param _index uint256 representing the index to be accessed of the requested tokens list + * @return uint256 token ID at the given index of the tokens list owned by the requested address + */ + function tokenOfOwnerByIndex( + address _owner, + uint256 _index + ) + public + view + returns (uint256) + { + require(_index < balanceOf(_owner)); + return ownedTokens[_owner][_index]; + } + + /** + * @dev Gets the total amount of tokens stored by the contract + * @return uint256 representing the total amount of tokens + */ + function totalSupply() public view returns (uint256) { + return cards.length; + } + + /** + * @dev Gets the token ID at a given index of all the tokens in this contract + * Reverts if the index is greater or equal to the total number of tokens + * @param _index uint256 representing the index to be accessed of the tokens list + * @return uint256 token ID at the given index of the tokens list + */ + function tokenByIndex(uint256 _index) public view returns (uint256) { + require(_index < totalSupply()); + return _index; + } + + /** + * @dev Internal function to add a token ID to the list of a given address + * @param _to address representing the new owner of the given token ID + * @param _tokenId uint256 ID of the token to be added to the tokens list of the given address + */ + function addTokenTo(address _to, uint256 _tokenId) internal { + super.addTokenTo(_to, _tokenId); + uint256 length = ownedTokens[_to].length; + // EDITED: prevent overflow + require(length == uint32(length)); + ownedTokens[_to].push(uint40(_tokenId)); + + ownedTokensIndex[_tokenId] = uint32(length); + } + + // EDITED + // have to have in order to use array rather than mapping + function addNewTokenTo(address _to, uint256 _tokenId) internal { + super.addNewTokenTo(_to, _tokenId); + uint256 length = ownedTokens[_to].length; + // EDITED: prevent overflow + require(length == uint32(length)); + ownedTokens[_to].push(uint40(_tokenId)); + ownedTokensIndex.push(uint32(length)); + } + + /** + * @dev Internal function to remove a token ID from the list of a given address + * @param _from address representing the previous owner of the given token ID + * @param _tokenId uint256 ID of the token to be removed from the tokens list of the given address + */ + function removeTokenFrom(address _from, uint256 _tokenId) internal { + super.removeTokenFrom(_from, _tokenId); + + uint32 tokenIndex = ownedTokensIndex[_tokenId]; + uint256 lastTokenIndex = ownedTokens[_from].length.sub(1); + uint40 lastToken = ownedTokens[_from][lastTokenIndex]; + + ownedTokens[_from][tokenIndex] = lastToken; + ownedTokens[_from][lastTokenIndex] = 0; + // Note that this will handle single-element arrays. In that case, both tokenIndex and lastTokenIndex are going to + // be zero. Then we can make sure that we will remove _tokenId from the ownedTokens list since we are first swapping + // the lastToken to the first position, and then dropping the element placed in the last position of the list + + ownedTokens[_from].length--; + ownedTokensIndex[_tokenId] = 0; + ownedTokensIndex[lastToken] = tokenIndex; + } + + /** + * @dev Gets the balance of the specified address - overrriden from previous to save gas + * @param _owner address to query the balance of + * @return uint256 representing the amount owned by the passed address + */ + function balanceOf(address _owner) public view returns (uint256) { + return ownedTokens[_owner].length; + } + +} + +contract CardOwnershipTwo is ERC721Token { + + uint public burnCount; + + function getActiveCards() public view returns (uint) { + return totalSupply() - burnCount; + } + + /** + * @param to : the address to which the card will be transferred + * @param id : the id of the card to be transferred + */ + function transfer(address to, uint id) public payable onlyOwnerOf(id) { + require(isTradable(cards[id].proto)); + require(to != address(0)); + + _transfer(msg.sender, to, id); + } + + function _transfer(address from, address to, uint id) internal { + + clearApproval(from, id); + + removeTokenFrom(from, id); + + addTokenTo(to, id); + + emit Transfer(from, to, id); + } + + /** + * @param to : the address to which the cards will be transferred + * @param ids : the ids of the cards to be transferred + */ + function transferAll(address to, uint[] memory ids) public payable { + for (uint i = 0; i < ids.length; i++) { + transfer(to, ids[i]); + } + } + + /** + * @param proposed : the claimed owner of the cards + * @param ids : the ids of the cards to check + * @return whether proposed owns all of the cards + */ + function ownsAll(address proposed, uint[] memory ids) public view returns (bool) { + require(ids.length > 0); + for (uint i = 0; i < ids.length; i++) { + if (!owns(proposed, ids[i])) { + return false; + } + } + return true; + } + + /** + * @param proposed : the claimed owner of the card + * @param id : the id of the card to check + * @return whether proposed owns the card + */ + function owns(address proposed, uint id) public view returns (bool) { + return ownerOf(id) == proposed; + } + + function burn(uint id) public onlyOwnerOf(id) { + burnCount++; + _burn(msg.sender, id); + } + + /** + * @param ids : the indices of the tokens to burn + */ + function burnAll(uint[] memory ids) public { + for (uint i = 0; i < ids.length; i++){ + burn(ids[i]); + } + } + + /** + * @param to : the address to approve for transfer + * @param id : the index of the card to be approved + */ + function approve(address to, uint id) public { + require(isTradable(cards[id].proto)); + super.approve(to, id); + } + + /** + * @param to : the address to approve for transfer + * @param ids : the indices of the cards to be approved + */ + function approveAll(address to, uint[] memory ids) public { + for (uint i = 0; i < ids.length; i++) { + approve(to, ids[i]); + } + } + + /** + * @param to : the address to which the token should be transferred + * @param id : the index of the token to transfer + */ + function transferFrom(address from, address to, uint id) public { + require(isTradable(cards[id].proto)); + super.transferFrom(from, to, id); + } + + /** + * @param to : the address to which the tokens should be transferred + * @param ids : the indices of the tokens to transfer + */ + function transferAllFrom(address from, address to, uint[] memory ids) public { + for (uint i = 0; i < ids.length; i++) { + transferFrom(from, to, ids[i]); + } + } + + /** + * @return the number of cards which have been burned + */ + function getBurnCount() public view returns (uint) { + return burnCount; + } + +} + +contract CardIntegrationTwo is CardOwnershipTwo { + + address[] public packs; + + event CardCreated(uint indexed id, uint16 proto, uint16 purity, address owner); + + function addPack(address approved) public onlyGovernor { + packs.push(approved); + } + + modifier onlyApprovedPacks { + require(_isApprovedPack()); + _; + } + + function _isApprovedPack() private view returns (bool) { + for (uint i = 0; i < packs.length; i++) { + if (msg.sender == address(packs[i])) { + return true; + } + } + return false; + } + + function createCard(address owner, uint16 proto, uint16 purity) public whenNotPaused onlyApprovedPacks returns (uint) { + ProtoCard memory card = protos[proto]; + require(card.season == currentSeason); + if (card.rarity == Rarity.Mythic) { + uint64 limit; + bool exists; + (limit, exists) = getLimit(proto); + require(!exists || limit > 0); + limits[proto].limit--; + } + return _createCard(owner, proto, purity); + } + + function _createCard(address owner, uint16 proto, uint16 purity) internal returns (uint) { + Card memory card = Card({ + proto: proto, + purity: purity + }); + + uint id = cards.push(card) - 1; + + _mint(owner, id); + + emit CardCreated(id, proto, purity, owner); + + return id; + } + + /*function combineCards(uint[] ids) public whenNotPaused { + require(ids.length == 5); + require(ownsAll(msg.sender, ids)); + Card memory first = cards[ids[0]]; + uint16 proto = first.proto; + uint8 shine = _getShine(first.purity); + require(shine < shineLimit); + uint16 puritySum = first.purity - (shine * 1000); + burn(ids[0]); + for (uint i = 1; i < ids.length; i++) { + Card memory next = cards[ids[i]]; + require(next.proto == proto); + require(_getShine(next.purity) == shine); + puritySum += (next.purity - (shine * 1000)); + burn(ids[i]); + } + uint16 newPurity = uint16(((shine + 1) * 1000) + (puritySum / ids.length)); + _createCard(msg.sender, proto, newPurity); + }*/ + + + // PURITY NOTES + // currently, we only + // however, to protect rarity, you'll never be abl + // this is enforced by the restriction in the create-card function + // no cards above this point can be found in packs + + + +} + +contract PreviousInterface { + + function ownerOf(uint id) public view returns (address); + + function getCard(uint id) public view returns (uint16, uint16); + + function totalSupply() public view returns (uint); + + function burnCount() public view returns (uint); + +} + +contract CardMigration is CardIntegrationTwo { + + constructor(PreviousInterface previous) public { + old = previous; + } + + // use interface to lower deployment cost + PreviousInterface old; + + mapping(uint => bool) public migrated; + + function migrate(uint id) public { + + require(!migrated[id]); + + migrated[id] = true; + + address owner = old.ownerOf(id); + + uint16 proto; + uint16 purity; + + (proto, purity) = old.getCard(id); + + _createCard(owner, proto, purity); + } + + function migrateAll(uint[] memory ids) public { + + for (uint i = 0; i < ids.length; i++){ + migrate(ids[i]); + } + + } + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractScenario008.sol b/src/test/resources/soliditycode/contractScenario008.sol new file mode 100644 index 00000000000..251b41bc6a2 --- /dev/null +++ b/src/test/resources/soliditycode/contractScenario008.sol @@ -0,0 +1,2050 @@ +//pragma solidity ^0.4.11; + + +/** + * @title Ownable + * @dev The Ownable contract has an owner address, and provides basic authorization control + * functions, this simplifies the implementation of "user permissions". + */ +contract Ownable { + address public owner; + + + /** + * @dev The Ownable constructor sets the original `owner` of the contract to the sender + * account. + */ + constructor() public { + owner = msg.sender; + } + + + /** + * @dev Throws if called by any account other than the owner. + */ + modifier onlyOwner() { + require(msg.sender == owner); + _; + } + + + /** + * @dev Allows the current owner to transfer control of the contract to a newOwner. + * @param newOwner The address to transfer ownership to. + */ + function transferOwnership(address newOwner) public onlyOwner { + if (newOwner != address(0)) { + owner = newOwner; + } + } + +} + + + + +/// @title A facet of KittyCore that manages special access privileges. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. +contract KittyAccessControl { + // This facet controls access control for CryptoKitties. There are four roles managed here: + // + // - The CEO: The CEO can reassign other roles and change the addresses of our dependent smart + // contracts. It is also the only role that can unpause the smart contract. It is initially + // set to the address that created the smart contract in the KittyCore constructor. + // + // - The CFO: The CFO can withdraw funds from KittyCore and its auction contracts. + // + // - The COO: The COO can release gen0 kitties to auction, and mint promo cats. + // + // It should be noted that these roles are distinct without overlap in their access abilities, the + // abilities listed for each role above are exhaustive. In particular, while the CEO can assign any + // address to any role, the CEO address itself doesn't have the ability to act in those roles. This + // restriction is intentional so that we aren't tempted to use the CEO address frequently out of + // convenience. The less we use an address, the less likely it is that we somehow compromise the + // account. + + /// @dev Emited when contract is upgraded - See README.md for updgrade plan + event ContractUpgrade(address newContract); + + // The addresses of the accounts (or contracts) that can execute actions within each roles. + address public ceoAddress; + address payable public cfoAddress; + address public cooAddress; + + // @dev Keeps track whether the contract is paused. When that is true, most actions are blocked + bool public paused = false; + + /// @dev Access modifier for CEO-only functionality + modifier onlyCEO() { + require(msg.sender == ceoAddress); + _; + } + + /// @dev Access modifier for CFO-only functionality + modifier onlyCFO() { + require(msg.sender == cfoAddress); + _; + } + + /// @dev Access modifier for COO-only functionality + modifier onlyCOO() { + require(msg.sender == cooAddress); + _; + } + + modifier onlyCLevel() { + require( + msg.sender == cooAddress || + msg.sender == ceoAddress || + msg.sender == cfoAddress + ); + _; + } + + /// @dev Assigns a new address to act as the CEO. Only available to the current CEO. + /// @param _newCEO The address of the new CEO + function setCEO(address _newCEO) external onlyCEO { + require(_newCEO != address(0)); + + ceoAddress = _newCEO; + } + + /// @dev Assigns a new address to act as the CFO. Only available to the current CEO. + /// @param _newCFO The address of the new CFO + function setCFO(address payable _newCFO) external onlyCEO { + require(_newCFO != address(0)); + + cfoAddress = _newCFO; + } + + /// @dev Assigns a new address to act as the COO. Only available to the current CEO. + /// @param _newCOO The address of the new COO + function setCOO(address _newCOO) external onlyCEO { + require(_newCOO != address(0)); + + cooAddress = _newCOO; + } + + /*** Pausable functionality adapted from OpenZeppelin ***/ + + /// @dev Modifier to allow actions only when the contract IS NOT paused + modifier whenNotPaused() { + require(!paused); + _; + } + + /// @dev Modifier to allow actions only when the contract IS paused + modifier whenPaused { + require(paused); + _; + } + + /// @dev Called by any "C-level" role to pause the contract. Used only when + /// a bug or exploit is detected and we need to limit damage. + function pause() external onlyCLevel whenNotPaused { + paused = true; + } + + /// @dev Unpauses the smart contract. Can only be called by the CEO, since + /// one reason we may pause the contract is when CFO or COO accounts are + /// compromised. + /// @notice This is public rather than external so it can be called by + /// derived contracts. + function unpause() public onlyCEO whenPaused { + // can't unpause if contract was upgraded + paused = false; + } +} + + + + +/// @title Base contract for CryptoKitties. Holds all common structs, events and base variables. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. +contract KittyBase is KittyAccessControl { + /*** EVENTS ***/ + + /// @dev The Birth event is fired whenever a new kitten comes into existence. This obviously + /// includes any time a cat is created through the giveBirth method, but it is also called + /// when a new gen0 cat is created. + event Birth(address owner, uint256 kittyId, uint256 matronId, uint256 sireId, uint256 genes); + + /// @dev Transfer event as defined in current draft of ERC721. Emitted every time a kitten + /// ownership is assigned, including births. + event Transfer(address from, address to, uint256 tokenId); + + /*** DATA TYPES ***/ + + /// @dev The main Kitty struct. Every cat in CryptoKitties is represented by a copy + /// of this structure, so great care was taken to ensure that it fits neatly into + /// exactly two 256-bit words. Note that the order of the members in this structure + /// is important because of the byte-packing rules used by Ethereum. + /// Ref: http://solidity.readthedocs.io/en/develop/miscellaneous.html + struct Kitty { + // The Kitty's genetic code is packed into these 256-bits, the format is + // sooper-sekret! A cat's genes never change. + uint256 genes; + + // The timestamp from the block when this cat came into existence. + uint64 birthTime; + + // The minimum timestamp after which this cat can engage in breeding + // activities again. This same timestamp is used for the pregnancy + // timer (for matrons) as well as the siring cooldown. + uint64 cooldownEndBlock; + + // The ID of the parents of this kitty, set to 0 for gen0 cats. + // Note that using 32-bit unsigned integers limits us to a "mere" + // 4 billion cats. This number might seem small until you realize + // that Ethereum currently has a limit of about 500 million + // transactions per year! So, this definitely won't be a problem + // for several years (even as Ethereum learns to scale). + uint32 matronId; + uint32 sireId; + + // Set to the ID of the sire cat for matrons that are pregnant, + // zero otherwise. A non-zero value here is how we know a cat + // is pregnant. Used to retrieve the genetic material for the new + // kitten when the birth transpires. + uint32 siringWithId; + + // Set to the index in the cooldown array (see below) that represents + // the current cooldown duration for this Kitty. This starts at zero + // for gen0 cats, and is initialized to floor(generation/2) for others. + // Incremented by one for each successful breeding action, regardless + // of whether this cat is acting as matron or sire. + uint16 cooldownIndex; + + // The "generation number" of this cat. Cats minted by the CK contract + // for sale are called "gen0" and have a generation number of 0. The + // generation number of all other cats is the larger of the two generation + // numbers of their parents, plus one. + // (i.e. max(matron.generation, sire.generation) + 1) + uint16 generation; + } + + /*** CONSTANTS ***/ + + /// @dev A lookup table indicating the cooldown duration after any successful + /// breeding action, called "pregnancy time" for matrons and "siring cooldown" + /// for sires. Designed such that the cooldown roughly doubles each time a cat + /// is bred, encouraging owners not to just keep breeding the same cat over + /// and over again. Caps out at one week (a cat can breed an unbounded number + /// of times, and the maximum cooldown is always seven days). + uint32[14] public cooldowns = [ + uint32(1 minutes), + uint32(2 minutes), + uint32(5 minutes), + uint32(10 minutes), + uint32(30 minutes), + uint32(1 hours), + uint32(2 hours), + uint32(4 hours), + uint32(8 hours), + uint32(16 hours), + uint32(1 days), + uint32(2 days), + uint32(4 days), + uint32(7 days) + ]; + + // An approximation of currently how many seconds are in between blocks. + uint256 public secondsPerBlock = 15; + + /*** STORAGE ***/ + + /// @dev An array containing the Kitty struct for all Kitties in existence. The ID + /// of each cat is actually an index into this array. Note that ID 0 is a negacat, + /// the unKitty, the mythical beast that is the parent of all gen0 cats. A bizarre + /// creature that is both matron and sire... to itself! Has an invalid genetic code. + /// In other words, cat ID 0 is invalid... ;-) + Kitty[] kitties; + + /// @dev A mapping from cat IDs to the address that owns them. All cats have + /// some valid owner address, even gen0 cats are created with a non-zero owner. + mapping (uint256 => address) public kittyIndexToOwner; + + // @dev A mapping from owner address to count of tokens that address owns. + // Used internally inside balanceOf() to resolve ownership count. + mapping (address => uint256) ownershipTokenCount; + + /// @dev A mapping from KittyIDs to an address that has been approved to call + /// transferFrom(). Each Kitty can only have one approved address for transfer + /// at any time. A zero value means no approval is outstanding. + mapping (uint256 => address) public kittyIndexToApproved; + + /// @dev A mapping from KittyIDs to an address that has been approved to use + /// this Kitty for siring via breedWith(). Each Kitty can only have one approved + /// address for siring at any time. A zero value means no approval is outstanding. + mapping (uint256 => address) public sireAllowedToAddress; + + /// @dev The address of the ClockAuction contract that handles sales of Kitties. This + /// same contract handles both peer-to-peer sales as well as the gen0 sales which are + /// initiated every 15 minutes. + SaleClockAuction public saleAuction; + + /// @dev The address of a custom ClockAuction subclassed contract that handles siring + /// auctions. Needs to be separate from saleAuction because the actions taken on success + /// after a sales and siring auction are quite different. + SiringClockAuction public siringAuction; + + /// @dev Assigns ownership of a specific Kitty to an address. + function _transfer(address _from, address _to, uint256 _tokenId) internal { + // Since the number of kittens is capped to 2^32 we can't overflow this + ownershipTokenCount[_to]++; + // transfer ownership + kittyIndexToOwner[_tokenId] = _to; + // When creating new kittens _from is 0x0, but we can't account that address. + if (_from != address(0)) { + ownershipTokenCount[_from]--; + // once the kitten is transferred also clear sire allowances + delete sireAllowedToAddress[_tokenId]; + // clear any previously approved ownership exchange + delete kittyIndexToApproved[_tokenId]; + } + // Emit the transfer event. + emit Transfer(_from, _to, _tokenId); + } + + /// @dev An internal method that creates a new kitty and stores it. This + /// method doesn't do any checking and should only be called when the + /// input data is known to be valid. Will generate both a Birth event + /// and a Transfer event. + /// @param _matronId The kitty ID of the matron of this cat (zero for gen0) + /// @param _sireId The kitty ID of the sire of this cat (zero for gen0) + /// @param _generation The generation number of this cat, must be computed by caller. + /// @param _genes The kitty's genetic code. + /// @param _owner The inital owner of this cat, must be non-zero (except for the unKitty, ID 0) + function _createKitty( + uint256 _matronId, + uint256 _sireId, + uint256 _generation, + uint256 _genes, + address _owner + ) + internal + returns (uint) + { + // These requires are not strictly necessary, our calling code should make + // sure that these conditions are never broken. However! _createKitty() is already + // an expensive call (for storage), and it doesn't hurt to be especially careful + // to ensure our data structures are always valid. + require(_matronId == uint256(uint32(_matronId))); + require(_sireId == uint256(uint32(_sireId))); + require(_generation == uint256(uint16(_generation))); + + // New kitty starts with the same cooldown as parent gen/2 + uint16 cooldownIndex = uint16(_generation / 2); + if (cooldownIndex > 13) { + cooldownIndex = 13; + } + + Kitty memory _kitty = Kitty({ + genes: _genes, + birthTime: uint64(now), + cooldownEndBlock: 0, + matronId: uint32(_matronId), + sireId: uint32(_sireId), + siringWithId: 0, + cooldownIndex: cooldownIndex, + generation: uint16(_generation) + }); + uint256 newKittenId = kitties.push(_kitty) - 1; + + // It's probably never going to happen, 4 billion cats is A LOT, but + // let's just be 100% sure we never let this happen. + require(newKittenId == uint256(uint32(newKittenId))); + + // emit the birth event + emit Birth( + _owner, + newKittenId, + uint256(_kitty.matronId), + uint256(_kitty.sireId), + _kitty.genes + ); + + // This will assign ownership, and also emit the Transfer event as + // per ERC721 draft + _transfer(address(0), _owner, newKittenId); + + return newKittenId; + } + + // Any C-level can fix how many seconds per blocks are currently observed. + function setSecondsPerBlock(uint256 secs) external onlyCLevel { + require(secs < cooldowns[0]); + secondsPerBlock = secs; + } +} + + +/// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens +/// @author Dieter Shirley (https://github.com/dete) +contract ERC721 { + // Required methods + function totalSupply() public view returns (uint256 total); + function balanceOf(address _owner) public view returns (uint256 balance); + function ownerOf(uint256 _tokenId) external view returns (address owner); + function approve(address _to, uint256 _tokenId) external; + function transfer(address _to, uint256 _tokenId) external; + function transferFrom(address _from, address _to, uint256 _tokenId) external; + + // Events + event Transfer(address from, address to, uint256 tokenId); + event Approval(address owner, address approved, uint256 tokenId); + + // Optional + // function name() public view returns (string name); + // function symbol() public view returns (string symbol); + // function tokensOfOwner(address _owner) external view returns (uint256[] tokenIds); + // function tokenMetadata(uint256 _tokenId, string _preferredTransport) public view returns (string infoUrl); + + // ERC-165 Compatibility (https://github.com/ethereum/EIPs/issues/165) + function supportsInterface(bytes4 _interfaceID) external view returns (bool); +} + + +/// @title The facet of the CryptoKitties core contract that manages ownership, ERC-721 (draft) compliant. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev Ref: https://github.com/ethereum/EIPs/issues/721 +/// See the KittyCore contract documentation to understand how the various contract facets are arranged. +contract KittyOwnership is ERC721, KittyBase { + + /// @notice Name and symbol of the non fungible token, as defined in ERC721. + string public constant name = "CryptoKitties"; + string public constant symbol = "CK"; + + // The contract that will return kitty metadata + ERC721Metadata public erc721Metadata; + + bytes4 constant InterfaceSignature_ERC165 = + bytes4(keccak256('supportsInterface(bytes4)')); + + bytes4 constant InterfaceSignature_ERC721 = + bytes4(keccak256('name()')) ^ + bytes4(keccak256('symbol()')) ^ + bytes4(keccak256('totalSupply()')) ^ + bytes4(keccak256('balanceOf(address)')) ^ + bytes4(keccak256('ownerOf(uint256)')) ^ + bytes4(keccak256('approve(address,uint256)')) ^ + bytes4(keccak256('transfer(address,uint256)')) ^ + bytes4(keccak256('transferFrom(address,address,uint256)')) ^ + bytes4(keccak256('tokensOfOwner(address)')) ^ + bytes4(keccak256('tokenMetadata(uint256,string)')); + + /// @notice Introspection interface as per ERC-165 (https://github.com/ethereum/EIPs/issues/165). + /// Returns true for any standardized interfaces implemented by this contract. We implement + /// ERC-165 (obviously!) and ERC-721. + function supportsInterface(bytes4 _interfaceID) external view returns (bool) + { + // DEBUG ONLY + //require((InterfaceSignature_ERC165 == 0x01ffc9a7) && (InterfaceSignature_ERC721 == 0x9a20483d)); + + return ((_interfaceID == InterfaceSignature_ERC165) || (_interfaceID == InterfaceSignature_ERC721)); + } + + /// @dev Set the address of the sibling contract that tracks metadata. + /// CEO only. + function setMetadataAddress(address _contractAddress) public onlyCEO { + erc721Metadata = ERC721Metadata(_contractAddress); + } + + // Internal utility functions: These functions all assume that their input arguments + // are valid. We leave it to public methods to sanitize their inputs and follow + // the required logic. + + /// @dev Checks if a given address is the current owner of a particular Kitty. + /// @param _claimant the address we are validating against. + /// @param _tokenId kitten id, only valid when > 0 + function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { + return kittyIndexToOwner[_tokenId] == _claimant; + } + + /// @dev Checks if a given address currently has transferApproval for a particular Kitty. + /// @param _claimant the address we are confirming kitten is approved for. + /// @param _tokenId kitten id, only valid when > 0 + function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) { + return kittyIndexToApproved[_tokenId] == _claimant; + } + + /// @dev Marks an address as being approved for transferFrom(), overwriting any previous + /// approval. Setting _approved to address(0) clears all transfer approval. + /// NOTE: _approve() does NOT send the Approval event. This is intentional because + /// _approve() and transferFrom() are used together for putting Kitties on auction, and + /// there is no value in spamming the log with Approval events in that case. + function _approve(uint256 _tokenId, address _approved) internal { + kittyIndexToApproved[_tokenId] = _approved; + } + + /// @notice Returns the number of Kitties owned by a specific address. + /// @param _owner The owner address to check. + /// @dev Required for ERC-721 compliance + function balanceOf(address _owner) public view returns (uint256 count) { + return ownershipTokenCount[_owner]; + } + + /// @notice Transfers a Kitty to another address. If transferring to a smart + /// contract be VERY CAREFUL to ensure that it is aware of ERC-721 (or + /// CryptoKitties specifically) or your Kitty may be lost forever. Seriously. + /// @param _to The address of the recipient, can be a user or contract. + /// @param _tokenId The ID of the Kitty to transfer. + /// @dev Required for ERC-721 compliance. + function transfer( + address _to, + uint256 _tokenId + ) + external + whenNotPaused + { + // Safety check to prevent against an unexpected 0x0 default. + require(_to != address(0)); + // Disallow transfers to this contract to prevent accidental misuse. + // The contract should never own any kitties (except very briefly + // after a gen0 cat is created and before it goes on auction). + require(_to != address(this)); + // Disallow transfers to the auction contracts to prevent accidental + // misuse. Auction contracts should only take ownership of kitties + // through the allow + transferFrom flow. + require(_to != address(saleAuction)); + require(_to != address(siringAuction)); + + // You can only send your own cat. + require(_owns(msg.sender, _tokenId)); + + // Reassign ownership, clear pending approvals, emit Transfer event. + _transfer(msg.sender, _to, _tokenId); + } + + /// @notice Grant another address the right to transfer a specific Kitty via + /// transferFrom(). This is the preferred flow for transfering NFTs to contracts. + /// @param _to The address to be granted transfer approval. Pass address(0) to + /// clear all approvals. + /// @param _tokenId The ID of the Kitty that can be transferred if this call succeeds. + /// @dev Required for ERC-721 compliance. + function approve( + address _to, + uint256 _tokenId + ) + external + whenNotPaused + { + // Only an owner can grant transfer approval. + require(_owns(msg.sender, _tokenId)); + + // Register the approval (replacing any previous approval). + _approve(_tokenId, _to); + + // Emit approval event. + emit Approval(msg.sender, _to, _tokenId); + } + + /// @notice Transfer a Kitty owned by another address, for which the calling address + /// has previously been granted transfer approval by the owner. + /// @param _from The address that owns the Kitty to be transfered. + /// @param _to The address that should take ownership of the Kitty. Can be any address, + /// including the caller. + /// @param _tokenId The ID of the Kitty to be transferred. + /// @dev Required for ERC-721 compliance. + function transferFrom( + address _from, + address _to, + uint256 _tokenId + ) + external + whenNotPaused + { + // Safety check to prevent against an unexpected 0x0 default. + require(_to != address(0)); + // Disallow transfers to this contract to prevent accidental misuse. + // The contract should never own any kitties (except very briefly + // after a gen0 cat is created and before it goes on auction). + require(_to != address(this)); + // Check for approval and valid ownership + require(_approvedFor(msg.sender, _tokenId)); + require(_owns(_from, _tokenId)); + + // Reassign ownership (also clears pending approvals and emits Transfer event). + _transfer(_from, _to, _tokenId); + } + + /// @notice Returns the total number of Kitties currently in existence. + /// @dev Required for ERC-721 compliance. + function totalSupply() public view returns (uint) { + return kitties.length - 1; + } + + /// @notice Returns the address currently assigned ownership of a given Kitty. + /// @dev Required for ERC-721 compliance. + function ownerOf(uint256 _tokenId) + external + view + returns (address owner) + { + owner = kittyIndexToOwner[_tokenId]; + + require(owner != address(0)); + } + + /// @notice Returns a list of all Kitty IDs assigned to an address. + /// @param _owner The owner whose Kitties we are interested in. + /// @dev This method MUST NEVER be called by smart contract code. First, it's fairly + /// expensive (it walks the entire Kitty array looking for cats belonging to owner), + /// but it also returns a dynamic array, which is only supported for web3 calls, and + /// not contract-to-contract calls. + function tokensOfOwner(address _owner) external view returns(uint256[] memory ownerTokens) { + uint256 tokenCount = balanceOf(_owner); + + if (tokenCount == 0) { + // Return an empty array + return new uint256[](0); + } else { + uint256[] memory result = new uint256[](tokenCount); + uint256 totalCats = totalSupply(); + uint256 resultIndex = 0; + + // We count on the fact that all cats have IDs starting at 1 and increasing + // sequentially up to the totalCat count. + uint256 catId; + + for (catId = 1; catId <= totalCats; catId++) { + if (kittyIndexToOwner[catId] == _owner) { + result[resultIndex] = catId; + resultIndex++; + } + } + + return result; + } + } + + /// @dev Adapted from memcpy() by @arachnid (Nick Johnson ) + /// This method is licenced under the Apache License. + /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol + function _memcpy(uint _dest, uint _src, uint _len) private view { + // Copy word-length chunks while possible + for(; _len >= 32; _len -= 32) { + assembly { + mstore(_dest, mload(_src)) + } + _dest += 32; + _src += 32; + } + + // Copy remaining bytes + uint256 mask = 256 ** (32 - _len) - 1; + assembly { + let srcpart := and(mload(_src), not(mask)) + let destpart := and(mload(_dest), mask) + mstore(_dest, or(destpart, srcpart)) + } + } + + /// @dev Adapted from toString(slice) by @arachnid (Nick Johnson ) + /// This method is licenced under the Apache License. + /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol + function _toString(bytes32[4] memory _rawBytes, uint256 _stringLength) private view returns (string memory) { + string memory outputString = new string(_stringLength); + uint256 outputPtr; + uint256 bytesPtr; + + assembly { + outputPtr := add(outputString, 32) + bytesPtr := _rawBytes + } + + _memcpy(outputPtr, bytesPtr, _stringLength); + + return outputString; + } + + /// @notice Returns a URI pointing to a metadata package for this token conforming to + /// ERC-721 (https://github.com/ethereum/EIPs/issues/721) + /// @param _tokenId The ID number of the Kitty whose metadata should be returned. + function tokenMetadata(uint256 _tokenId, string calldata _preferredTransport) external view returns (string memory infoUrl) { + require( address(erc721Metadata) != address(0)); + bytes32[4] memory buffer; + uint256 count; + (buffer, count) = erc721Metadata.getMetadata(_tokenId, _preferredTransport); + + return _toString(buffer, count); + } +} + + + + +/// @title A facet of KittyCore that manages Kitty siring, gestation, and birth. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. +contract KittyBreeding is KittyOwnership { + + /// @dev The Pregnant event is fired when two cats successfully breed and the pregnancy + /// timer begins for the matron. + event Pregnant(address owner, uint256 matronId, uint256 sireId, uint256 cooldownEndBlock); + + /// @notice The minimum payment required to use breedWithAuto(). This fee goes towards + /// the gas cost paid by whatever calls giveBirth(), and can be dynamically updated by + /// the COO role as the gas price changes. + uint256 public autoBirthFee = 2 sun; + + // Keeps track of number of pregnant kitties. + uint256 public pregnantKitties; + + /// @dev The address of the sibling contract that is used to implement the sooper-sekret + /// genetic combination algorithm. + GeneScienceInterface public geneScience; + + /// @dev Update the address of the genetic contract, can only be called by the CEO. + /// @param _address An address of a GeneScience contract instance to be used from this point forward. + function setGeneScienceAddress(address _address) external onlyCEO { + GeneScienceInterface candidateContract = GeneScienceInterface(_address); + + // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 + require(candidateContract.isGeneScience()); + + // Set the new contract address + geneScience = candidateContract; + } + + /// @dev Checks that a given kitten is able to breed. Requires that the + /// current cooldown is finished (for sires) and also checks that there is + /// no pending pregnancy. + function _isReadyToBreed(Kitty memory _kit) internal view returns (bool) { + // In addition to checking the cooldownEndBlock, we also need to check to see if + // the cat has a pending birth; there can be some period of time between the end + // of the pregnacy timer and the birth event. + return (_kit.siringWithId == 0) && (_kit.cooldownEndBlock <= uint64(block.number)); + } + + /// @dev Check if a sire has authorized breeding with this matron. True if both sire + /// and matron have the same owner, or if the sire has given siring permission to + /// the matron's owner (via approveSiring()). + function _isSiringPermitted(uint256 _sireId, uint256 _matronId) internal view returns (bool) { + address matronOwner = kittyIndexToOwner[_matronId]; + address sireOwner = kittyIndexToOwner[_sireId]; + + // Siring is okay if they have same owner, or if the matron's owner was given + // permission to breed with this sire. + return (matronOwner == sireOwner || sireAllowedToAddress[_sireId] == matronOwner); + } + + /// @dev Set the cooldownEndTime for the given Kitty, based on its current cooldownIndex. + /// Also increments the cooldownIndex (unless it has hit the cap). + /// @param _kitten A reference to the Kitty in storage which needs its timer started. + function _triggerCooldown(Kitty storage _kitten) internal { + // Compute an estimation of the cooldown time in blocks (based on current cooldownIndex). + _kitten.cooldownEndBlock = uint64((cooldowns[_kitten.cooldownIndex]/secondsPerBlock) + block.number); + + // Increment the breeding count, clamping it at 13, which is the length of the + // cooldowns array. We could check the array size dynamically, but hard-coding + // this as a constant saves gas. Yay, Solidity! + if (_kitten.cooldownIndex < 13) { + _kitten.cooldownIndex += 1; + } + } + + /// @notice Grants approval to another user to sire with one of your Kitties. + /// @param _addr The address that will be able to sire with your Kitty. Set to + /// address(0) to clear all siring approvals for this Kitty. + /// @param _sireId A Kitty that you own that _addr will now be able to sire with. + function approveSiring(address _addr, uint256 _sireId) + external + whenNotPaused + { + require(_owns(msg.sender, _sireId)); + sireAllowedToAddress[_sireId] = _addr; + } + + /// @dev Updates the minimum payment required for calling giveBirthAuto(). Can only + /// be called by the COO address. (This fee is used to offset the gas cost incurred + /// by the autobirth daemon). + function setAutoBirthFee(uint256 val) external onlyCOO { + autoBirthFee = val; + } + + /// @dev Checks to see if a given Kitty is pregnant and (if so) if the gestation + /// period has passed. + function _isReadyToGiveBirth(Kitty memory _matron) private view returns (bool) { + return (_matron.siringWithId != 0) && (_matron.cooldownEndBlock <= uint64(block.number)); + } + + /// @notice Checks that a given kitten is able to breed (i.e. it is not pregnant or + /// in the middle of a siring cooldown). + /// @param _kittyId reference the id of the kitten, any user can inquire about it + function isReadyToBreed(uint256 _kittyId) + public + view + returns (bool) + { + require(_kittyId > 0); + Kitty storage kit = kitties[_kittyId]; + return _isReadyToBreed(kit); + } + + /// @dev Checks whether a kitty is currently pregnant. + /// @param _kittyId reference the id of the kitten, any user can inquire about it + function isPregnant(uint256 _kittyId) + public + view + returns (bool) + { + require(_kittyId > 0); + // A kitty is pregnant if and only if this field is set + return kitties[_kittyId].siringWithId != 0; + } + + /// @dev Internal check to see if a given sire and matron are a valid mating pair. DOES NOT + /// check ownership permissions (that is up to the caller). + /// @param _matron A reference to the Kitty struct of the potential matron. + /// @param _matronId The matron's ID. + /// @param _sire A reference to the Kitty struct of the potential sire. + /// @param _sireId The sire's ID + function _isValidMatingPair( + Kitty storage _matron, + uint256 _matronId, + Kitty storage _sire, + uint256 _sireId + ) + private + view + returns(bool) + { + // A Kitty can't breed with itself! + if (_matronId == _sireId) { + return false; + } + + // Kitties can't breed with their parents. + if (_matron.matronId == _sireId || _matron.sireId == _sireId) { + return false; + } + if (_sire.matronId == _matronId || _sire.sireId == _matronId) { + return false; + } + + // We can short circuit the sibling check (below) if either cat is + // gen zero (has a matron ID of zero). + if (_sire.matronId == 0 || _matron.matronId == 0) { + return true; + } + + // Kitties can't breed with full or half siblings. + if (_sire.matronId == _matron.matronId || _sire.matronId == _matron.sireId) { + return false; + } + if (_sire.sireId == _matron.matronId || _sire.sireId == _matron.sireId) { + return false; + } + + // Everything seems cool! Let's get DTF. + return true; + } + + /// @dev Internal check to see if a given sire and matron are a valid mating pair for + /// breeding via auction (i.e. skips ownership and siring approval checks). + function _canBreedWithViaAuction(uint256 _matronId, uint256 _sireId) + internal + view + returns (bool) + { + Kitty storage matron = kitties[_matronId]; + Kitty storage sire = kitties[_sireId]; + return _isValidMatingPair(matron, _matronId, sire, _sireId); + } + + /// @notice Checks to see if two cats can breed together, including checks for + /// ownership and siring approvals. Does NOT check that both cats are ready for + /// breeding (i.e. breedWith could still fail until the cooldowns are finished). + /// TODO: Shouldn't this check pregnancy and cooldowns?!? + /// @param _matronId The ID of the proposed matron. + /// @param _sireId The ID of the proposed sire. + function canBreedWith(uint256 _matronId, uint256 _sireId) + external + view + returns(bool) + { + require(_matronId > 0); + require(_sireId > 0); + Kitty storage matron = kitties[_matronId]; + Kitty storage sire = kitties[_sireId]; + return _isValidMatingPair(matron, _matronId, sire, _sireId) && + _isSiringPermitted(_sireId, _matronId); + } + + /// @dev Internal utility function to initiate breeding, assumes that all breeding + /// requirements have been checked. + function _breedWith(uint256 _matronId, uint256 _sireId) internal { + // Grab a reference to the Kitties from storage. + Kitty storage sire = kitties[_sireId]; + Kitty storage matron = kitties[_matronId]; + + // Mark the matron as pregnant, keeping track of who the sire is. + matron.siringWithId = uint32(_sireId); + + // Trigger the cooldown for both parents. + _triggerCooldown(sire); + _triggerCooldown(matron); + + // Clear siring permission for both parents. This may not be strictly necessary + // but it's likely to avoid confusion! + delete sireAllowedToAddress[_matronId]; + delete sireAllowedToAddress[_sireId]; + + // Every time a kitty gets pregnant, counter is incremented. + pregnantKitties++; + + // Emit the pregnancy event. + emit Pregnant(kittyIndexToOwner[_matronId], _matronId, _sireId, matron.cooldownEndBlock); + } + + /// @notice Breed a Kitty you own (as matron) with a sire that you own, or for which you + /// have previously been given Siring approval. Will either make your cat pregnant, or will + /// fail entirely. Requires a pre-payment of the fee given out to the first caller of giveBirth() + /// @param _matronId The ID of the Kitty acting as matron (will end up pregnant if successful) + /// @param _sireId The ID of the Kitty acting as sire (will begin its siring cooldown if successful) + function breedWithAuto(uint256 _matronId, uint256 _sireId) + external + payable + whenNotPaused + { + // Checks for payment. + require(msg.value >= autoBirthFee); + + // Caller must own the matron. + require(_owns(msg.sender, _matronId)); + + // Neither sire nor matron are allowed to be on auction during a normal + // breeding operation, but we don't need to check that explicitly. + // For matron: The caller of this function can't be the owner of the matron + // because the owner of a Kitty on auction is the auction house, and the + // auction house will never call breedWith(). + // For sire: Similarly, a sire on auction will be owned by the auction house + // and the act of transferring ownership will have cleared any oustanding + // siring approval. + // Thus we don't need to spend gas explicitly checking to see if either cat + // is on auction. + + // Check that matron and sire are both owned by caller, or that the sire + // has given siring permission to caller (i.e. matron's owner). + // Will fail for _sireId = 0 + require(_isSiringPermitted(_sireId, _matronId)); + + // Grab a reference to the potential matron + Kitty storage matron = kitties[_matronId]; + + // Make sure matron isn't pregnant, or in the middle of a siring cooldown + require(_isReadyToBreed(matron)); + + // Grab a reference to the potential sire + Kitty storage sire = kitties[_sireId]; + + // Make sure sire isn't pregnant, or in the middle of a siring cooldown + require(_isReadyToBreed(sire)); + + // Test that these cats are a valid mating pair. + require(_isValidMatingPair( + matron, + _matronId, + sire, + _sireId + )); + + // All checks passed, kitty gets pregnant! + _breedWith(_matronId, _sireId); + } + + /// @notice Have a pregnant Kitty give birth! + /// @param _matronId A Kitty ready to give birth. + /// @return The Kitty ID of the new kitten. + /// @dev Looks at a given Kitty and, if pregnant and if the gestation period has passed, + /// combines the genes of the two parents to create a new kitten. The new Kitty is assigned + /// to the current owner of the matron. Upon successful completion, both the matron and the + /// new kitten will be ready to breed again. Note that anyone can call this function (if they + /// are willing to pay the gas!), but the new kitten always goes to the mother's owner. + function giveBirth(uint256 _matronId) + external + whenNotPaused + returns(uint256) + { + // Grab a reference to the matron in storage. + Kitty storage matron = kitties[_matronId]; + + // Check that the matron is a valid cat. + require(matron.birthTime != 0); + + // Check that the matron is pregnant, and that its time has come! + require(_isReadyToGiveBirth(matron)); + + // Grab a reference to the sire in storage. + uint256 sireId = matron.siringWithId; + Kitty storage sire = kitties[sireId]; + + // Determine the higher generation number of the two parents + uint16 parentGen = matron.generation; + if (sire.generation > matron.generation) { + parentGen = sire.generation; + } + + // Call the sooper-sekret gene mixing operation. + uint256 childGenes = geneScience.mixGenes(matron.genes, sire.genes, matron.cooldownEndBlock - 1); + + // Make the new kitten! + address owner = kittyIndexToOwner[_matronId]; + uint256 kittenId = _createKitty(_matronId, matron.siringWithId, parentGen + 1, childGenes, owner); + + // Clear the reference to sire from the matron (REQUIRED! Having siringWithId + // set is what marks a matron as being pregnant.) + delete matron.siringWithId; + + // Every time a kitty gives birth counter is decremented. + pregnantKitties--; + + // Send the balance fee to the person who made birth happen. + msg.sender.transfer(autoBirthFee); + + // return the new kitten's ID + return kittenId; + } +} + + + +/// @title Handles creating auctions for sale and siring of kitties. +/// This wrapper of ReverseAuction exists only so that users can create +/// auctions with only one transaction. +contract KittyAuction is KittyBreeding { + + // @notice The auction contract variables are defined in KittyBase to allow + // us to refer to them in KittyOwnership to prevent accidental transfers. + // `saleAuction` refers to the auction for gen0 and p2p sale of kitties. + // `siringAuction` refers to the auction for siring rights of kitties. + + /// @dev Sets the reference to the sale auction. + /// @param _address - Address of sale contract. + function setSaleAuctionAddress(address _address) external onlyCEO { + SaleClockAuction candidateContract = SaleClockAuction(_address); + + // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 + require(candidateContract.isSaleClockAuction()); + + // Set the new contract address + saleAuction = candidateContract; + } + + /// @dev Sets the reference to the siring auction. + /// @param _address - Address of siring contract. + function setSiringAuctionAddress(address _address) external onlyCEO { + SiringClockAuction candidateContract = SiringClockAuction(_address); + + // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 + require(candidateContract.isSiringClockAuction()); + + // Set the new contract address + siringAuction = candidateContract; + } + + /// @dev Put a kitty up for auction. + /// Does some ownership trickery to create auctions in one tx. + function createSaleAuction( + uint256 _kittyId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration + ) + external + whenNotPaused + { + // Auction contract checks input sizes + // If kitty is already on any auction, this will throw + // because it will be owned by the auction contract. + require(_owns(msg.sender, _kittyId)); + // Ensure the kitty is not pregnant to prevent the auction + // contract accidentally receiving ownership of the child. + // NOTE: the kitty IS allowed to be in a cooldown. + require(!isPregnant(_kittyId)); + _approve(_kittyId, address(saleAuction)); + // Sale auction throws if inputs are invalid and clears + // transfer and sire approval after escrowing the kitty. + saleAuction.createAuction( + _kittyId, + _startingPrice, + _endingPrice, + _duration, + msg.sender + ); + } + + /// @dev Put a kitty up for auction to be sire. + /// Performs checks to ensure the kitty can be sired, then + /// delegates to reverse auction. + function createSiringAuction( + uint256 _kittyId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration + ) + external + whenNotPaused + { + // Auction contract checks input sizes + // If kitty is already on any auction, this will throw + // because it will be owned by the auction contract. + require(_owns(msg.sender, _kittyId)); + require(isReadyToBreed(_kittyId)); + _approve(_kittyId, address(siringAuction)); + // Siring auction throws if inputs are invalid and clears + // transfer and sire approval after escrowing the kitty. + siringAuction.createAuction( + _kittyId, + _startingPrice, + _endingPrice, + _duration, + msg.sender + ); + } + + /// @dev Completes a siring auction by bidding. + /// Immediately breeds the winning matron with the sire on auction. + /// @param _sireId - ID of the sire on auction. + /// @param _matronId - ID of the matron owned by the bidder. + function bidOnSiringAuction( + uint256 _sireId, + uint256 _matronId + ) + external + payable + whenNotPaused + { + // Auction contract checks input sizes + require(_owns(msg.sender, _matronId)); + require(isReadyToBreed(_matronId)); + require(_canBreedWithViaAuction(_matronId, _sireId)); + + // Define the current price of the auction. + uint256 currentPrice = siringAuction.getCurrentPrice(_sireId); + require(msg.value >= currentPrice + autoBirthFee); + + // Siring auction will throw if the bid fails. + siringAuction.bid.value(msg.value - autoBirthFee)(_sireId); + _breedWith(uint32(_matronId), uint32(_sireId)); + } + + /// @dev Transfers the balance of the sale auction contract + /// to the KittyCore contract. We use two-step withdrawal to + /// prevent two transfer calls in the auction bid function. + function withdrawAuctionBalances() external onlyCLevel { + saleAuction.withdrawBalance(); + siringAuction.withdrawBalance(); + } +} + + +/// @title all functions related to creating kittens +contract KittyMinting is KittyAuction { + + // Limits the number of cats the contract owner can ever create. + uint256 public constant PROMO_CREATION_LIMIT = 5000; + uint256 public constant GEN0_CREATION_LIMIT = 45000; + + // Constants for gen0 auctions. + uint256 public constant GEN0_STARTING_PRICE = 10 sun; + uint256 public constant GEN0_AUCTION_DURATION = 1 days; + + // Counts the number of cats the contract owner has created. + uint256 public promoCreatedCount; + uint256 public gen0CreatedCount; + + /// @dev we can create promo kittens, up to a limit. Only callable by COO + /// @param _genes the encoded genes of the kitten to be created, any value is accepted + /// @param _owner the future owner of the created kittens. Default to contract COO + function createPromoKitty(uint256 _genes, address _owner) external onlyCOO { + address kittyOwner = _owner; + if (kittyOwner == address(0)) { + kittyOwner = cooAddress; + } + require(promoCreatedCount < PROMO_CREATION_LIMIT); + + promoCreatedCount++; + _createKitty(0, 0, 0, _genes, kittyOwner); + } + + /// @dev Creates a new gen0 kitty with the given genes and + /// creates an auction for it. + function createGen0Auction(uint256 _genes) external onlyCOO { + require(gen0CreatedCount < GEN0_CREATION_LIMIT); + + uint256 kittyId = _createKitty(0, 0, 0, _genes, address(this)); + _approve(kittyId, address(saleAuction)); + + saleAuction.createAuction( + kittyId, + _computeNextGen0Price(), + 0, + GEN0_AUCTION_DURATION, + address(uint160(address(this))) + ); + + gen0CreatedCount++; + } + + /// @dev Computes the next gen0 auction starting price, given + /// the average of the past 5 prices + 50%. + function _computeNextGen0Price() internal view returns (uint256) { + uint256 avePrice = saleAuction.averageGen0SalePrice(); + + // Sanity check to ensure we don't overflow arithmetic + require(avePrice == uint256(uint128(avePrice))); + + uint256 nextPrice = avePrice + (avePrice / 2); + + // We never auction for less than starting price + if (nextPrice < GEN0_STARTING_PRICE) { + nextPrice = GEN0_STARTING_PRICE; + } + + return nextPrice; + } +} + + + +/// @title CryptoKitties: Collectible, breedable, and oh-so-adorable cats on the Ethereum blockchain. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev The main CryptoKitties contract, keeps track of kittens so they don't wander around and get lost. +contract KittyCore is KittyMinting { + + // This is the main CryptoKitties contract. In order to keep our code seperated into logical sections, + // we've broken it up in two ways. First, we have several seperately-instantiated sibling contracts + // that handle auctions and our super-top-secret genetic combination algorithm. The auctions are + // seperate since their logic is somewhat complex and there's always a risk of subtle bugs. By keeping + // them in their own contracts, we can upgrade them without disrupting the main contract that tracks + // kitty ownership. The genetic combination algorithm is kept seperate so we can open-source all of + // the rest of our code without making it _too_ easy for folks to figure out how the genetics work. + // Don't worry, I'm sure someone will reverse engineer it soon enough! + // + // Secondly, we break the core contract into multiple files using inheritence, one for each major + // facet of functionality of CK. This allows us to keep related code bundled together while still + // avoiding a single giant file with everything in it. The breakdown is as follows: + // + // - KittyBase: This is where we define the most fundamental code shared throughout the core + // functionality. This includes our main data storage, constants and data types, plus + // internal functions for managing these items. + // + // - KittyAccessControl: This contract manages the various addresses and constraints for operations + // that can be executed only by specific roles. Namely CEO, CFO and COO. + // + // - KittyOwnership: This provides the methods required for basic non-fungible token + // transactions, following the draft ERC-721 spec (https://github.com/ethereum/EIPs/issues/721). + // + // - KittyBreeding: This file contains the methods necessary to breed cats together, including + // keeping track of siring offers, and relies on an external genetic combination contract. + // + // - KittyAuctions: Here we have the public methods for auctioning or bidding on cats or siring + // services. The actual auction functionality is handled in two sibling contracts (one + // for sales and one for siring), while auction creation and bidding is mostly mediated + // through this facet of the core contract. + // + // - KittyMinting: This final facet contains the functionality we use for creating new gen0 cats. + // We can make up to 5000 "promo" cats that can be given away (especially important when + // the community is new), and all others can only be created and then immediately put up + // for auction via an algorithmically determined starting price. Regardless of how they + // are created, there is a hard limit of 50k gen0 cats. After that, it's all up to the + // community to breed, breed, breed! + + // Set in case the core contract is broken and an upgrade is required + address public newContractAddress; + + /// @notice Creates the main CryptoKitties smart contract instance. + constructor() public { + // Starts paused. + paused = true; + + // the creator of the contract is the initial CEO + ceoAddress = msg.sender; + + // the creator of the contract is also the initial COO + cooAddress = msg.sender; + + // start with the mythical kitten 0 - so we don't have generation-0 parent issues + _createKitty(0, 0, 0, uint256(-1), address(0)); + } + + /// @dev Used to mark the smart contract as upgraded, in case there is a serious + /// breaking bug. This method does nothing but keep track of the new contract and + /// emit a message indicating that the new address is set. It's up to clients of this + /// contract to update to the new contract address in that case. (This contract will + /// be paused indefinitely if such an upgrade takes place.) + /// @param _v2Address new address + function setNewAddress(address _v2Address) external onlyCEO whenPaused { + // See README.md for updgrade plan + newContractAddress = _v2Address; + emit ContractUpgrade(_v2Address); + } + + /// @notice No tipping! + /// @dev Reject all Ether from being sent here, unless it's from one of the + /// two auction contracts. (Hopefully, we can prevent user accidents.) + function() external payable { + require( + msg.sender == address(saleAuction) || + msg.sender == address(siringAuction) + ); + } + + /// @notice Returns all the relevant information about a specific kitty. + /// @param _id The ID of the kitty of interest. + function getKitty(uint256 _id) + external + view + returns ( + bool isGestating, + bool isReady, + uint256 cooldownIndex, + uint256 nextActionAt, + uint256 siringWithId, + uint256 birthTime, + uint256 matronId, + uint256 sireId, + uint256 generation, + uint256 genes + ) { + Kitty storage kit = kitties[_id]; + + // if this variable is 0 then it's not gestating + isGestating = (kit.siringWithId != 0); + isReady = (kit.cooldownEndBlock <= block.number); + cooldownIndex = uint256(kit.cooldownIndex); + nextActionAt = uint256(kit.cooldownEndBlock); + siringWithId = uint256(kit.siringWithId); + birthTime = uint256(kit.birthTime); + matronId = uint256(kit.matronId); + sireId = uint256(kit.sireId); + generation = uint256(kit.generation); + genes = kit.genes; + } + + /// @dev Override unpause so it requires all external contract addresses + /// to be set before contract can be unpaused. Also, we can't have + /// newContractAddress set either, because then the contract was upgraded. + /// @notice This is public rather than external so we can call super.unpause + /// without using an expensive CALL. + + function unpause() public onlyCEO whenPaused { + require(address(saleAuction) != address(0)); + require(address(siringAuction) != address(0)); + require(address(geneScience) != address(0)); + require(newContractAddress == address(0)); + + // Actually unpause the contract. + super.unpause(); + } + + // @dev Allows the CFO to capture the balance available to the contract. + function withdrawBalance() external onlyCFO { + uint256 balance = address(this).balance; + // Subtract all the currently pregnant kittens we have, plus 1 of margin. + uint256 subtractFees = (pregnantKitties + 1) * autoBirthFee; + + if (balance > subtractFees) { + cfoAddress.transfer(balance - subtractFees); + } + } +} + + + + + + + + + + + + + +// // Auction wrapper functions + + +// Auction wrapper functions + + + + + + + +/// @title SEKRETOOOO +contract GeneScienceInterface { + + function isGeneScience() public pure returns (bool){ + return true; + } + + /// @dev given genes of kitten 1 & 2, return a genetic combination - may have a random factor + /// @param genes1 genes of mom + /// @param genes2 genes of sire + /// @return the genes that are supposed to be passed down the child + function mixGenes(uint256 genes1, uint256 genes2, uint256 targetBlock) public pure returns (uint256){ + + return (genes1+genes2+targetBlock)/2; + + +} +} + + + + + + + + + + + + + + + + +/// @title The external contract that is responsible for generating metadata for the kitties, +/// it has one function that will return the data as bytes. +contract ERC721Metadata { + /// @dev Given a token Id, returns a byte array that is supposed to be converted into string. + function getMetadata(uint256 _tokenId, string memory) public view returns (bytes32[4] memory buffer, uint256 count) { + if (_tokenId == 1) { + buffer[0] = "Hello World! :D"; + count = 15; + } else if (_tokenId == 2) { + buffer[0] = "I would definitely choose a medi"; + buffer[1] = "um length string."; + count = 49; + } else if (_tokenId == 3) { + buffer[0] = "Lorem ipsum dolor sit amet, mi e"; + buffer[1] = "st accumsan dapibus augue lorem,"; + buffer[2] = " tristique vestibulum id, libero"; + buffer[3] = " suscipit varius sapien aliquam."; + count = 128; + } + } +} + + + + + + + + + + + + + + + +/// @title Auction Core +/// @dev Contains models, variables, and internal methods for the auction. +/// @notice We omit a fallback function to prevent accidental sends to this contract. +contract ClockAuctionBase { + + // Represents an auction on an NFT + struct Auction { + // Current owner of NFT + address payable seller; + // Price (in wei) at beginning of auction + uint128 startingPrice; + // Price (in wei) at end of auction + uint128 endingPrice; + // Duration (in seconds) of auction + uint64 duration; + // Time when auction started + // NOTE: 0 if this auction has been concluded + uint64 startedAt; + } + + // Reference to contract tracking NFT ownership + ERC721 public nonFungibleContract; + + // Cut owner takes on each auction, measured in basis points (1/100 of a percent). + // Values 0-10,000 map to 0%-100% + uint256 public ownerCut; + + // Map from token ID to their corresponding auction. + mapping (uint256 => Auction) tokenIdToAuction; + + event AuctionCreated(uint256 tokenId, uint256 startingPrice, uint256 endingPrice, uint256 duration); + event AuctionSuccessful(uint256 tokenId, uint256 totalPrice, address winner); + event AuctionCancelled(uint256 tokenId); + + /// @dev Returns true if the claimant owns the token. + /// @param _claimant - Address claiming to own the token. + /// @param _tokenId - ID of token whose ownership to verify. + function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { + return (nonFungibleContract.ownerOf(_tokenId) == _claimant); + } + + /// @dev Escrows the NFT, assigning ownership to this contract. + /// Throws if the escrow fails. + /// @param _owner - Current owner address of token to escrow. + /// @param _tokenId - ID of token whose approval to verify. + function _escrow(address _owner, uint256 _tokenId) internal { + // it will throw if transfer fails + nonFungibleContract.transferFrom(_owner, address(this), _tokenId); + } + + /// @dev Transfers an NFT owned by this contract to another address. + /// Returns true if the transfer succeeds. + /// @param _receiver - Address to transfer NFT to. + /// @param _tokenId - ID of token to transfer. + function _transfer(address _receiver, uint256 _tokenId) internal { + // it will throw if transfer fails + nonFungibleContract.transfer(_receiver, _tokenId); + } + + /// @dev Adds an auction to the list of open auctions. Also fires the + /// AuctionCreated event. + /// @param _tokenId The ID of the token to be put on auction. + /// @param _auction Auction to add. + function _addAuction(uint256 _tokenId, Auction memory _auction) internal { + // Require that all auctions have a duration of + // at least one minute. (Keeps our math from getting hairy!) + require(_auction.duration >= 1 minutes); + + tokenIdToAuction[_tokenId] = _auction; + + emit AuctionCreated( + uint256(_tokenId), + uint256(_auction.startingPrice), + uint256(_auction.endingPrice), + uint256(_auction.duration) + ); + } + + /// @dev Cancels an auction unconditionally. + function _cancelAuction(uint256 _tokenId, address _seller) internal { + _removeAuction(_tokenId); + _transfer(_seller, _tokenId); + emit AuctionCancelled(_tokenId); + } + + /// @dev Computes the price and transfers winnings. + /// Does NOT transfer ownership of token. + function _bid(uint256 _tokenId, uint256 _bidAmount) + internal + returns (uint256) + { + // Get a reference to the auction struct + Auction storage auction = tokenIdToAuction[_tokenId]; + + // Explicitly check that this auction is currently live. + // (Because of how Ethereum mappings work, we can't just count + // on the lookup above failing. An invalid _tokenId will just + // return an auction object that is all zeros.) + require(_isOnAuction(auction)); + + // Check that the bid is greater than or equal to the current price + uint256 price = _currentPrice(auction); + require(_bidAmount >= price); + + // Grab a reference to the seller before the auction struct + // gets deleted. + address payable seller = auction.seller; + + // The bid is good! Remove the auction before sending the fees + // to the sender so we can't have a reentrancy attack. + _removeAuction(_tokenId); + + // Transfer proceeds to seller (if there are any!) + if (price > 0) { + // Calculate the auctioneer's cut. + // (NOTE: _computeCut() is guaranteed to return a + // value <= price, so this subtraction can't go negative.) + uint256 auctioneerCut = _computeCut(price); + uint256 sellerProceeds = price - auctioneerCut; + + // NOTE: Doing a transfer() in the middle of a complex + // method like this is generally discouraged because of + // reentrancy attacks and DoS attacks if the seller is + // a contract with an invalid fallback function. We explicitly + // guard against reentrancy attacks by removing the auction + // before calling transfer(), and the only thing the seller + // can DoS is the sale of their own asset! (And if it's an + // accident, they can call cancelAuction(). ) + seller.transfer(sellerProceeds); + } + + // Calculate any excess funds included with the bid. If the excess + // is anything worth worrying about, transfer it back to bidder. + // NOTE: We checked above that the bid amount is greater than or + // equal to the price so this cannot underflow. + uint256 bidExcess = _bidAmount - price; + + // Return the funds. Similar to the previous transfer, this is + // not susceptible to a re-entry attack because the auction is + // removed before any transfers occur. + msg.sender.transfer(bidExcess); + + // Tell the world! + emit AuctionSuccessful(_tokenId, price, msg.sender); + + return price; + } + + /// @dev Removes an auction from the list of open auctions. + /// @param _tokenId - ID of NFT on auction. + function _removeAuction(uint256 _tokenId) internal { + delete tokenIdToAuction[_tokenId]; + } + + /// @dev Returns true if the NFT is on auction. + /// @param _auction - Auction to check. + function _isOnAuction(Auction storage _auction) internal view returns (bool) { + return (_auction.startedAt > 0); + } + + /// @dev Returns current price of an NFT on auction. Broken into two + /// functions (this one, that computes the duration from the auction + /// structure, and the other that does the price computation) so we + /// can easily test that the price computation works correctly. + function _currentPrice(Auction storage _auction) + internal + view + returns (uint256) + { + uint256 secondsPassed = 0; + + // A bit of insurance against negative values (or wraparound). + // Probably not necessary (since Ethereum guarnatees that the + // now variable doesn't ever go backwards). + if (now > _auction.startedAt) { + secondsPassed = now - _auction.startedAt; + } + + return _computeCurrentPrice( + _auction.startingPrice, + _auction.endingPrice, + _auction.duration, + secondsPassed + ); + } + + /// @dev Computes the current price of an auction. Factored out + /// from _currentPrice so we can run extensive unit tests. + /// When testing, make this function public and turn on + /// `Current price computation` test suite. + function _computeCurrentPrice( + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration, + uint256 _secondsPassed + ) + internal + pure + returns (uint256) + { + // NOTE: We don't use SafeMath (or similar) in this function because + // all of our public functions carefully cap the maximum values for + // time (at 64-bits) and currency (at 128-bits). _duration is + // also known to be non-zero (see the require() statement in + // _addAuction()) + if (_secondsPassed >= _duration) { + // We've reached the end of the dynamic pricing portion + // of the auction, just return the end price. + return _endingPrice; + } else { + // Starting price can be higher than ending price (and often is!), so + // this delta can be negative. + int256 totalPriceChange = int256(_endingPrice) - int256(_startingPrice); + + // This multiplication can't overflow, _secondsPassed will easily fit within + // 64-bits, and totalPriceChange will easily fit within 128-bits, their product + // will always fit within 256-bits. + int256 currentPriceChange = totalPriceChange * int256(_secondsPassed) / int256(_duration); + + // currentPriceChange can be negative, but if so, will have a magnitude + // less that _startingPrice. Thus, this result will always end up positive. + int256 currentPrice = int256(_startingPrice) + currentPriceChange; + + return uint256(currentPrice); + } + } + + /// @dev Computes owner's cut of a sale. + /// @param _price - Sale price of NFT. + function _computeCut(uint256 _price) internal view returns (uint256) { + // NOTE: We don't use SafeMath (or similar) in this function because + // all of our entry functions carefully cap the maximum values for + // currency (at 128-bits), and ownerCut <= 10000 (see the require() + // statement in the ClockAuction constructor). The result of this + // function is always guaranteed to be <= _price. + return _price * ownerCut / 10000; + } + +} + + + + + + + +/** + * @title Pausable + * @dev Base contract which allows children to implement an emergency stop mechanism. + */ +contract Pausable is Ownable { + event Pause(); + event Unpause(); + + bool public paused = false; + + + /** + * @dev modifier to allow actions only when the contract IS paused + */ + modifier whenNotPaused() { + require(!paused); + _; + } + + /** + * @dev modifier to allow actions only when the contract IS NOT paused + */ + modifier whenPaused { + require(paused); + _; + } + + /** + * @dev called by the owner to pause, triggers stopped state + */ + function pause() onlyOwner whenNotPaused public returns (bool) { + paused = true; + emit Pause(); + return true; + } + + /** + * @dev called by the owner to unpause, returns to normal state + */ + function unpause() onlyOwner whenPaused public returns (bool) { + paused = false; + emit Unpause(); + return true; + } +} + + +/// @title Clock auction for non-fungible tokens. +/// @notice We omit a fallback function to prevent accidental sends to this contract. +contract ClockAuction is Pausable, ClockAuctionBase { + + /// @dev The ERC-165 interface signature for ERC-721. + /// Ref: https://github.com/ethereum/EIPs/issues/165 + /// Ref: https://github.com/ethereum/EIPs/issues/721 + bytes4 constant InterfaceSignature_ERC721 = bytes4(0x9a20483d); + + /// @dev Constructor creates a reference to the NFT ownership contract + /// and verifies the owner cut is in the valid range. + /// @param _nftAddress - address of a deployed contract implementing + /// the Nonfungible Interface. + /// @param _cut - percent cut the owner takes on each auction, must be + /// between 0-10,000. + constructor(address _nftAddress, uint256 _cut) public { + require(_cut <= 10000); + ownerCut = _cut; + + ERC721 candidateContract = ERC721(_nftAddress); + require(candidateContract.supportsInterface(InterfaceSignature_ERC721)); + nonFungibleContract = candidateContract; + } + + /// @dev Remove all Ether from the contract, which is the owner's cuts + /// as well as any Ether sent directly to the contract address. + /// Always transfers to the NFT contract, but can be called either by + /// the owner or the NFT contract. + function withdrawBalance() external { + address payable nftAddress = address(uint160(address(nonFungibleContract))); + + require( + msg.sender == owner || + msg.sender == nftAddress + ); + // We are using this boolean method to make sure that even if one fails it will still work + bool res = nftAddress.send(address(this).balance); + } + + /// @dev Creates and begins a new auction. + /// @param _tokenId - ID of token to auction, sender must be owner. + /// @param _startingPrice - Price of item (in wei) at beginning of auction. + /// @param _endingPrice - Price of item (in wei) at end of auction. + /// @param _duration - Length of time to move between starting + /// price and ending price (in seconds). + /// @param _seller - Seller, if not the message sender + function createAuction( + uint256 _tokenId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration, + address payable _seller + ) + external + whenNotPaused + { + // Sanity check that no inputs overflow how many bits we've allocated + // to store them in the auction struct. + require(_startingPrice == uint256(uint128(_startingPrice))); + require(_endingPrice == uint256(uint128(_endingPrice))); + require(_duration == uint256(uint64(_duration))); + + require(_owns(msg.sender, _tokenId)); + _escrow(msg.sender, _tokenId); + Auction memory auction = Auction( + _seller, + uint128(_startingPrice), + uint128(_endingPrice), + uint64(_duration), + uint64(now) + ); + _addAuction(_tokenId, auction); + } + + /// @dev Bids on an open auction, completing the auction and transferring + /// ownership of the NFT if enough Ether is supplied. + /// @param _tokenId - ID of token to bid on. + function bid(uint256 _tokenId) + external + payable + whenNotPaused + { + // _bid will throw if the bid or funds transfer fails + _bid(_tokenId, msg.value); + _transfer(msg.sender, _tokenId); + } + + /// @dev Cancels an auction that hasn't been won yet. + /// Returns the NFT to original owner. + /// @notice This is a state-modifying function that can + /// be called while the contract is paused. + /// @param _tokenId - ID of token on auction + function cancelAuction(uint256 _tokenId) + external + { + Auction storage auction = tokenIdToAuction[_tokenId]; + require(_isOnAuction(auction)); + address seller = auction.seller; + require(msg.sender == seller); + _cancelAuction(_tokenId, seller); + } + + /// @dev Cancels an auction when the contract is paused. + /// Only the owner may do this, and NFTs are returned to + /// the seller. This should only be used in emergencies. + /// @param _tokenId - ID of the NFT on auction to cancel. + function cancelAuctionWhenPaused(uint256 _tokenId) + whenPaused + onlyOwner + external + { + Auction storage auction = tokenIdToAuction[_tokenId]; + require(_isOnAuction(auction)); + _cancelAuction(_tokenId, auction.seller); + } + + /// @dev Returns auction info for an NFT on auction. + /// @param _tokenId - ID of NFT on auction. + function getAuction(uint256 _tokenId) + external + view + returns + ( + address seller, + uint256 startingPrice, + uint256 endingPrice, + uint256 duration, + uint256 startedAt + ) { + Auction storage auction = tokenIdToAuction[_tokenId]; + require(_isOnAuction(auction)); + return ( + auction.seller, + auction.startingPrice, + auction.endingPrice, + auction.duration, + auction.startedAt + ); + } + + /// @dev Returns the current price of an auction. + /// @param _tokenId - ID of the token price we are checking. + function getCurrentPrice(uint256 _tokenId) + external + view + returns (uint256) + { + Auction storage auction = tokenIdToAuction[_tokenId]; + require(_isOnAuction(auction)); + return _currentPrice(auction); + } + +} + + +/// @title Reverse auction modified for siring +/// @notice We omit a fallback function to prevent accidental sends to this contract. +contract SiringClockAuction is ClockAuction { + + // @dev Sanity check that allows us to ensure that we are pointing to the + // right auction in our setSiringAuctionAddress() call. + bool public isSiringClockAuction = true; + + // Delegate constructor + constructor(address _nftAddr, uint256 _cut) public + ClockAuction(_nftAddr, _cut) {} + + /// @dev Creates and begins a new auction. Since this function is wrapped, + /// require sender to be KittyCore contract. + /// @param _tokenId - ID of token to auction, sender must be owner. + /// @param _startingPrice - Price of item (in wei) at beginning of auction. + /// @param _endingPrice - Price of item (in wei) at end of auction. + /// @param _duration - Length of auction (in seconds). + /// @param _seller - Seller, if not the message sender + function createAuction( + uint256 _tokenId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration, + address payable _seller + ) + external + { + // Sanity check that no inputs overflow how many bits we've allocated + // to store them in the auction struct. + require(_startingPrice == uint256(uint128(_startingPrice))); + require(_endingPrice == uint256(uint128(_endingPrice))); + require(_duration == uint256(uint64(_duration))); + + require(msg.sender == address(nonFungibleContract)); + _escrow(_seller, _tokenId); + Auction memory auction = Auction( + _seller, + uint128(_startingPrice), + uint128(_endingPrice), + uint64(_duration), + uint64(now) + ); + _addAuction(_tokenId, auction); + } + + /// @dev Places a bid for siring. Requires the sender + /// is the KittyCore contract because all bid methods + /// should be wrapped. Also returns the kitty to the + /// seller rather than the winner. + function bid(uint256 _tokenId) + external + payable + { + require(msg.sender == address(nonFungibleContract)); + address seller = tokenIdToAuction[_tokenId].seller; + // _bid checks that token ID is valid and will throw if bid fails + _bid(_tokenId, msg.value); + // We transfer the kitty back to the seller, the winner will get + // the offspring + _transfer(seller, _tokenId); + } + +} + + + + + +/// @title Clock auction modified for sale of kitties +/// @notice We omit a fallback function to prevent accidental sends to this contract. +contract SaleClockAuction is ClockAuction { + + // @dev Sanity check that allows us to ensure that we are pointing to the + // right auction in our setSaleAuctionAddress() call. + bool public isSaleClockAuction = true; + + // Tracks last 5 sale price of gen0 kitty sales + uint256 public gen0SaleCount; + uint256[5] public lastGen0SalePrices; + + // Delegate constructor + constructor(address _nftAddr, uint256 _cut) public + ClockAuction(_nftAddr, _cut) {} + + /// @dev Creates and begins a new auction. + /// @param _tokenId - ID of token to auction, sender must be owner. + /// @param _startingPrice - Price of item (in wei) at beginning of auction. + /// @param _endingPrice - Price of item (in wei) at end of auction. + /// @param _duration - Length of auction (in seconds). + /// @param _seller - Seller, if not the message sender + function createAuction( + uint256 _tokenId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration, + address payable _seller + ) + external + { + // Sanity check that no inputs overflow how many bits we've allocated + // to store them in the auction struct. + require(_startingPrice == uint256(uint128(_startingPrice))); + require(_endingPrice == uint256(uint128(_endingPrice))); + require(_duration == uint256(uint64(_duration))); + + require(msg.sender == address(nonFungibleContract)); + _escrow(_seller, _tokenId); + Auction memory auction = Auction( + _seller, + uint128(_startingPrice), + uint128(_endingPrice), + uint64(_duration), + uint64(now) + ); + _addAuction(_tokenId, auction); + } + + /// @dev Updates lastSalePrice if seller is the nft contract + /// Otherwise, works the same as default bid method. + function bid(uint256 _tokenId) + external + payable + { + // _bid verifies token ID size + address seller = tokenIdToAuction[_tokenId].seller; + uint256 price = _bid(_tokenId, msg.value); + _transfer(msg.sender, _tokenId); + + // If not a gen0 auction, exit + if (seller == address(nonFungibleContract)) { + // Track gen0 sale prices + lastGen0SalePrices[gen0SaleCount % 5] = price; + gen0SaleCount++; + } + } + + function averageGen0SalePrice() external view returns (uint256) { + uint256 sum = 0; + for (uint256 i = 0; i < 5; i++) { + sum += lastGen0SalePrices[i]; + } + return sum / 5; + } + +} + + + + + + + diff --git a/src/test/resources/soliditycode/contractScenario009.sol b/src/test/resources/soliditycode/contractScenario009.sol new file mode 100644 index 00000000000..fb0b76db240 --- /dev/null +++ b/src/test/resources/soliditycode/contractScenario009.sol @@ -0,0 +1,51 @@ +//pragma solidity ^0.4.0; + +library Set { + // We define a new struct datatype that will be used to + // hold its data in the calling contract. + struct Data { mapping(uint => bool) flags; } + + // Note that the first parameter is of type "storage + // reference" and thus only its storage address and not + // its contents is passed as part of the call. This is a + // special feature of library functions. It is idiomatic + // to call the first parameter 'self', if the function can + // be seen as a method of that object. + function insert (Data storage self, uint value) public + returns (bool) + { + if (self.flags[value]) + return false; // already there + self.flags[value] = true; + return true; + } + + function remove(Data storage self, uint value) public + returns (bool) + { + if (!self.flags[value]) + return false; // not there + self.flags[value] = false; + return true; + } + + function contains(Data storage self, uint value) public + returns (bool) + { + return self.flags[value]; + } +} + + +contract C { + Set.Data knownValues; + + function register(uint value) public { + // The library functions can be called without a + // specific instance of the library, since the + // "instance" will be the current contract. + if (!Set.insert(knownValues, value)) + revert(); + } + // In this contract, we can also directly access knownValues.flags, if we want. +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractScenario010.sol b/src/test/resources/soliditycode/contractScenario010.sol new file mode 100644 index 00000000000..f665ea9686e --- /dev/null +++ b/src/test/resources/soliditycode/contractScenario010.sol @@ -0,0 +1,107 @@ +//pragma solidity ^0.4.11; + +contract TRON_ERC721 { + //name + function name() view public returns (string memory name){ + return "Tron ERC721 Token"; + } + //symbol + function symbol() view public returns (string memory symbol){ + return "T721T"; + } + + //totalSupply + + function totalSupply() view public returns (uint256 supply){ + uint256 totalSupply = 1000000000000; + return totalSupply; + } + + mapping(address => uint) private balances; + function balanceOf(address _owner) view public returns (uint balance) + { + return balances[_owner]; + } + + + mapping(uint256 => address) private tokenOwners; + mapping(uint256 => bool) private tokenExists; + function ownerOf(uint256 _tokenId) view public returns (address owner) { + require(tokenExists[_tokenId]); + return tokenOwners[_tokenId]; + } + + + mapping(address => mapping (address => uint256)) allowed; + function approve(address _to, uint256 _tokenId) public{ + require(msg.sender == ownerOf(_tokenId)); + require(msg.sender != _to); + allowed[msg.sender][_to] = _tokenId; + emit Approval(msg.sender, _to, _tokenId); + } + + + function takeOwnership(uint256 _tokenId) public { + require(tokenExists[_tokenId]); + address oldOwner = ownerOf(_tokenId); + address newOwner = msg.sender; + require(newOwner != oldOwner); + require(allowed[oldOwner][newOwner] == _tokenId); + balances[oldOwner] -= 1; + tokenOwners[_tokenId] = newOwner; + balances[newOwner] += 1; + emit Transfer(oldOwner, newOwner, _tokenId); + } + + + mapping(address => mapping(uint256 => uint256)) private ownerTokens; + function removeFromTokenList(address owner, uint256 _tokenId) private { + for(uint256 i = 0;ownerTokens[owner][i] != _tokenId;i++){ + ownerTokens[owner][i] = 0; + } + } + + function transfer(address _to, uint256 _tokenId) public{ + address currentOwner = msg.sender; + address newOwner = _to; + require(tokenExists[_tokenId]); + require(currentOwner == ownerOf(_tokenId)); + require(currentOwner != newOwner); + require(newOwner != address(0)); + address oldOwner =currentOwner; + removeFromTokenList(oldOwner,_tokenId); + balances[oldOwner] -= 1; + tokenOwners[_tokenId] = newOwner; + balances[newOwner] += 1; + emit Transfer(oldOwner, newOwner, _tokenId); + } + + function transferFrom(address _from,address _to, uint256 _tokenId) public{ + address currentOwner = _from; + address newOwner = _to; + require(tokenExists[_tokenId]); + require(currentOwner == ownerOf(_tokenId)); + require(currentOwner != newOwner); + require(newOwner != address(0)); + address oldOwner =currentOwner; + removeFromTokenList(oldOwner,_tokenId); + balances[oldOwner] -= 1; + tokenOwners[_tokenId] = newOwner; + balances[newOwner] += 1; + emit Transfer(oldOwner, newOwner, _tokenId); + } + + + function tokenOfOwnerByIndex(address _owner, uint256 _index) view public returns (uint tokenId){ + return ownerTokens[_owner][_index]; + } + + + mapping(uint256 => string) tokenLinks; + function tokenMetadata(uint256 _tokenId) view public returns (string memory infoUrl) { + return tokenLinks[_tokenId]; + } + // Events + event Transfer(address indexed _from, address indexed _to, uint256 _tokenId); + event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId); +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractScenario011.sol b/src/test/resources/soliditycode/contractScenario011.sol new file mode 100644 index 00000000000..74fe819be31 --- /dev/null +++ b/src/test/resources/soliditycode/contractScenario011.sol @@ -0,0 +1,2050 @@ +//pragma solidity ^0.4.11; + + +/** + * @title Ownable + * @dev The Ownable contract has an owner address, and provides basic authorization control + * functions, this simplifies the implementation of "user permissions". + */ +contract Ownable { + address public owner; + + + /** + * @dev The Ownable constructor sets the original `owner` of the contract to the sender + * account. + */ + constructor() public { + owner = msg.sender; + } + + + /** + * @dev Throws if called by any account other than the owner. + */ + modifier onlyOwner() { + require(msg.sender == owner); + _; + } + + + /** + * @dev Allows the current owner to transfer control of the contract to a newOwner. + * @param newOwner The address to transfer ownership to. + */ + function transferOwnership(address newOwner) public onlyOwner { + if (newOwner != address(0)) { + owner = newOwner; + } + } + +} + + + + +/// @title A facet of KittyCore that manages special access privileges. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. +contract KittyAccessControl { + // This facet controls access control for CryptoKitties. There are four roles managed here: + // + // - The CEO: The CEO can reassign other roles and change the addresses of our dependent smart + // contracts. It is also the only role that can unpause the smart contract. It is initially + // set to the address that created the smart contract in the KittyCore constructor. + // + // - The CFO: The CFO can withdraw funds from KittyCore and its auction contracts. + // + // - The COO: The COO can release gen0 kitties to auction, and mint promo cats. + // + // It should be noted that these roles are distinct without overlap in their access abilities, the + // abilities listed for each role above are exhaustive. In particular, while the CEO can assign any + // address to any role, the CEO address itself doesn't have the ability to act in those roles. This + // restriction is intentional so that we aren't tempted to use the CEO address frequently out of + // convenience. The less we use an address, the less likely it is that we somehow compromise the + // account. + + /// @dev Emited when contract is upgraded - See README.md for updgrade plan + event ContractUpgrade(address newContract); + + // The addresses of the accounts (or contracts) that can execute actions within each roles. + address public ceoAddress; + address payable public cfoAddress; + address public cooAddress; + + // @dev Keeps track whether the contract is paused. When that is true, most actions are blocked + bool public paused = false; + + /// @dev Access modifier for CEO-only functionality + modifier onlyCEO() { + require(msg.sender == ceoAddress); + _; + } + + /// @dev Access modifier for CFO-only functionality + modifier onlyCFO() { + require(msg.sender == cfoAddress); + _; + } + + /// @dev Access modifier for COO-only functionality + modifier onlyCOO() { + require(msg.sender == cooAddress); + _; + } + + modifier onlyCLevel() { + require( + msg.sender == cooAddress || + msg.sender == ceoAddress || + msg.sender == cfoAddress + ); + _; + } + + /// @dev Assigns a new address to act as the CEO. Only available to the current CEO. + /// @param _newCEO The address of the new CEO + function setCEO(address _newCEO) external onlyCEO { + require(_newCEO != address(0)); + + ceoAddress = _newCEO; + } + + /// @dev Assigns a new address to act as the CFO. Only available to the current CEO. + /// @param _newCFO The address of the new CFO + function setCFO(address payable _newCFO) external onlyCEO { + require(_newCFO != address(0)); + + cfoAddress = _newCFO; + } + + /// @dev Assigns a new address to act as the COO. Only available to the current CEO. + /// @param _newCOO The address of the new COO + function setCOO(address _newCOO) external onlyCEO { + require(_newCOO != address(0)); + + cooAddress = _newCOO; + } + + /*** Pausable functionality adapted from OpenZeppelin ***/ + + /// @dev Modifier to allow actions only when the contract IS NOT paused + modifier whenNotPaused() { + require(!paused); + _; + } + + /// @dev Modifier to allow actions only when the contract IS paused + modifier whenPaused { + require(paused); + _; + } + + /// @dev Called by any "C-level" role to pause the contract. Used only when + /// a bug or exploit is detected and we need to limit damage. + function pause() external onlyCLevel whenNotPaused { + paused = true; + } + + /// @dev Unpauses the smart contract. Can only be called by the CEO, since + /// one reason we may pause the contract is when CFO or COO accounts are + /// compromised. + /// @notice This is public rather than external so it can be called by + /// derived contracts. + function unpause() public onlyCEO whenPaused { + // can't unpause if contract was upgraded + paused = false; + } +} + + + + +/// @title Base contract for CryptoKitties. Holds all common structs, events and base variables. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. +contract KittyBase is KittyAccessControl { + /*** EVENTS ***/ + + /// @dev The Birth event is fired whenever a new kitten comes into existence. This obviously + /// includes any time a cat is created through the giveBirth method, but it is also called + /// when a new gen0 cat is created. + event Birth(address owner, uint256 kittyId, uint256 matronId, uint256 sireId, uint256 genes); + + /// @dev Transfer event as defined in current draft of ERC721. Emitted every time a kitten + /// ownership is assigned, including births. + event Transfer(address from, address to, uint256 tokenId); + + /*** DATA TYPES ***/ + + /// @dev The main Kitty struct. Every cat in CryptoKitties is represented by a copy + /// of this structure, so great care was taken to ensure that it fits neatly into + /// exactly two 256-bit words. Note that the order of the members in this structure + /// is important because of the byte-packing rules used by Ethereum. + /// Ref: http://solidity.readthedocs.io/en/develop/miscellaneous.html + struct Kitty { + // The Kitty's genetic code is packed into these 256-bits, the format is + // sooper-sekret! A cat's genes never change. + uint256 genes; + + // The timestamp from the block when this cat came into existence. + uint64 birthTime; + + // The minimum timestamp after which this cat can engage in breeding + // activities again. This same timestamp is used for the pregnancy + // timer (for matrons) as well as the siring cooldown. + uint64 cooldownEndBlock; + + // The ID of the parents of this kitty, set to 0 for gen0 cats. + // Note that using 32-bit unsigned integers limits us to a "mere" + // 4 billion cats. This number might seem small until you realize + // that Ethereum currently has a limit of about 500 million + // transactions per year! So, this definitely won't be a problem + // for several years (even as Ethereum learns to scale). + uint32 matronId; + uint32 sireId; + + // Set to the ID of the sire cat for matrons that are pregnant, + // zero otherwise. A non-zero value here is how we know a cat + // is pregnant. Used to retrieve the genetic material for the new + // kitten when the birth transpires. + uint32 siringWithId; + + // Set to the index in the cooldown array (see below) that represents + // the current cooldown duration for this Kitty. This starts at zero + // for gen0 cats, and is initialized to floor(generation/2) for others. + // Incremented by one for each successful breeding action, regardless + // of whether this cat is acting as matron or sire. + uint16 cooldownIndex; + + // The "generation number" of this cat. Cats minted by the CK contract + // for sale are called "gen0" and have a generation number of 0. The + // generation number of all other cats is the larger of the two generation + // numbers of their parents, plus one. + // (i.e. max(matron.generation, sire.generation) + 1) + uint16 generation; + } + + /*** CONSTANTS ***/ + + /// @dev A lookup table indicating the cooldown duration after any successful + /// breeding action, called "pregnancy time" for matrons and "siring cooldown" + /// for sires. Designed such that the cooldown roughly doubles each time a cat + /// is bred, encouraging owners not to just keep breeding the same cat over + /// and over again. Caps out at one week (a cat can breed an unbounded number + /// of times, and the maximum cooldown is always seven days). + uint32[14] public cooldowns = [ + uint32(1 minutes), + uint32(2 minutes), + uint32(5 minutes), + uint32(10 minutes), + uint32(30 minutes), + uint32(1 hours), + uint32(2 hours), + uint32(4 hours), + uint32(8 hours), + uint32(16 hours), + uint32(1 days), + uint32(2 days), + uint32(4 days), + uint32(7 days) + ]; + + // An approximation of currently how many seconds are in between blocks. + uint256 public secondsPerBlock = 15; + + /*** STORAGE ***/ + + /// @dev An array containing the Kitty struct for all Kitties in existence. The ID + /// of each cat is actually an index into this array. Note that ID 0 is a negacat, + /// the unKitty, the mythical beast that is the parent of all gen0 cats. A bizarre + /// creature that is both matron and sire... to itself! Has an invalid genetic code. + /// In other words, cat ID 0 is invalid... ;-) + Kitty[] kitties; + + /// @dev A mapping from cat IDs to the address that owns them. All cats have + /// some valid owner address, even gen0 cats are created with a non-zero owner. + mapping (uint256 => address) public kittyIndexToOwner; + + // @dev A mapping from owner address to count of tokens that address owns. + // Used internally inside balanceOf() to resolve ownership count. + mapping (address => uint256) ownershipTokenCount; + + /// @dev A mapping from KittyIDs to an address that has been approved to call + /// transferFrom(). Each Kitty can only have one approved address for transfer + /// at any time. A zero value means no approval is outstanding. + mapping (uint256 => address) public kittyIndexToApproved; + + /// @dev A mapping from KittyIDs to an address that has been approved to use + /// this Kitty for siring via breedWith(). Each Kitty can only have one approved + /// address for siring at any time. A zero value means no approval is outstanding. + mapping (uint256 => address) public sireAllowedToAddress; + + /// @dev The address of the ClockAuction contract that handles sales of Kitties. This + /// same contract handles both peer-to-peer sales as well as the gen0 sales which are + /// initiated every 15 minutes. + SaleClockAuction public saleAuction; + + /// @dev The address of a custom ClockAuction subclassed contract that handles siring + /// auctions. Needs to be separate from saleAuction because the actions taken on success + /// after a sales and siring auction are quite different. + SiringClockAuction public siringAuction; + + /// @dev Assigns ownership of a specific Kitty to an address. + function _transfer(address _from, address _to, uint256 _tokenId) internal { + // Since the number of kittens is capped to 2^32 we can't overflow this + ownershipTokenCount[_to]++; + // transfer ownership + kittyIndexToOwner[_tokenId] = _to; + // When creating new kittens _from is 0x0, but we can't account that address. + if (_from != address(0)) { + ownershipTokenCount[_from]--; + // once the kitten is transferred also clear sire allowances + delete sireAllowedToAddress[_tokenId]; + // clear any previously approved ownership exchange + delete kittyIndexToApproved[_tokenId]; + } + // Emit the transfer event. + emit Transfer(_from, _to, _tokenId); + } + + /// @dev An internal method that creates a new kitty and stores it. This + /// method doesn't do any checking and should only be called when the + /// input data is known to be valid. Will generate both a Birth event + /// and a Transfer event. + /// @param _matronId The kitty ID of the matron of this cat (zero for gen0) + /// @param _sireId The kitty ID of the sire of this cat (zero for gen0) + /// @param _generation The generation number of this cat, must be computed by caller. + /// @param _genes The kitty's genetic code. + /// @param _owner The inital owner of this cat, must be non-zero (except for the unKitty, ID 0) + function _createKitty( + uint256 _matronId, + uint256 _sireId, + uint256 _generation, + uint256 _genes, + address _owner + ) + internal + returns (uint) + { + // These requires are not strictly necessary, our calling code should make + // sure that these conditions are never broken. However! _createKitty() is already + // an expensive call (for storage), and it doesn't hurt to be especially careful + // to ensure our data structures are always valid. + require(_matronId == uint256(uint32(_matronId))); + require(_sireId == uint256(uint32(_sireId))); + require(_generation == uint256(uint16(_generation))); + + // New kitty starts with the same cooldown as parent gen/2 + uint16 cooldownIndex = uint16(_generation / 2); + if (cooldownIndex > 13) { + cooldownIndex = 13; + } + + Kitty memory _kitty = Kitty({ + genes: _genes, + birthTime: uint64(now), + cooldownEndBlock: 0, + matronId: uint32(_matronId), + sireId: uint32(_sireId), + siringWithId: 0, + cooldownIndex: cooldownIndex, + generation: uint16(_generation) + }); + uint256 newKittenId = kitties.push(_kitty) - 1; + + // It's probably never going to happen, 4 billion cats is A LOT, but + // let's just be 100% sure we never let this happen. + require(newKittenId == uint256(uint32(newKittenId))); + + // emit the birth event + emit Birth( + _owner, + newKittenId, + uint256(_kitty.matronId), + uint256(_kitty.sireId), + _kitty.genes + ); + + // This will assign ownership, and also emit the Transfer event as + // per ERC721 draft + _transfer(address(0), _owner, newKittenId); + + return newKittenId; + } + + // Any C-level can fix how many seconds per blocks are currently observed. + function setSecondsPerBlock(uint256 secs) external onlyCLevel { + require(secs < cooldowns[0]); + secondsPerBlock = secs; + } +} + + +/// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens +/// @author Dieter Shirley (https://github.com/dete) +contract ERC721 { + // Required methods + function totalSupply() public view returns (uint256 total); + function balanceOf(address _owner) public view returns (uint256 balance); + function ownerOf(uint256 _tokenId) external view returns (address owner); + function approve(address _to, uint256 _tokenId) external; + function transfer(address _to, uint256 _tokenId) external; + function transferFrom(address _from, address _to, uint256 _tokenId) external; + + // Events + event Transfer(address from, address to, uint256 tokenId); + event Approval(address owner, address approved, uint256 tokenId); + + // Optional + // function name() public view returns (string name); + // function symbol() public view returns (string symbol); + // function tokensOfOwner(address _owner) external view returns (uint256[] tokenIds); + // function tokenMetadata(uint256 _tokenId, string _preferredTransport) public view returns (string infoUrl); + + // ERC-165 Compatibility (https://github.com/ethereum/EIPs/issues/165) + function supportsInterface(bytes4 _interfaceID) external view returns (bool); +} + + +/// @title The facet of the CryptoKitties core contract that manages ownership, ERC-721 (draft) compliant. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev Ref: https://github.com/ethereum/EIPs/issues/721 +/// See the KittyCore contract documentation to understand how the various contract facets are arranged. +contract KittyOwnership is ERC721, KittyBase { + + /// @notice Name and symbol of the non fungible token, as defined in ERC721. + string public constant name = "CryptoKitties"; + string public constant symbol = "CK"; + + // The contract that will return kitty metadata + ERC721Metadata public erc721Metadata; + + bytes4 constant InterfaceSignature_ERC165 = + bytes4(keccak256('supportsInterface(bytes4)')); + + bytes4 constant InterfaceSignature_ERC721 = + bytes4(keccak256('name()')) ^ + bytes4(keccak256('symbol()')) ^ + bytes4(keccak256('totalSupply()')) ^ + bytes4(keccak256('balanceOf(address)')) ^ + bytes4(keccak256('ownerOf(uint256)')) ^ + bytes4(keccak256('approve(address,uint256)')) ^ + bytes4(keccak256('transfer(address,uint256)')) ^ + bytes4(keccak256('transferFrom(address,address,uint256)')) ^ + bytes4(keccak256('tokensOfOwner(address)')) ^ + bytes4(keccak256('tokenMetadata(uint256,string)')); + + /// @notice Introspection interface as per ERC-165 (https://github.com/ethereum/EIPs/issues/165). + /// Returns true for any standardized interfaces implemented by this contract. We implement + /// ERC-165 (obviously!) and ERC-721. + function supportsInterface(bytes4 _interfaceID) external view returns (bool) + { + // DEBUG ONLY + //require((InterfaceSignature_ERC165 == 0x01ffc9a7) && (InterfaceSignature_ERC721 == 0x9a20483d)); + + return ((_interfaceID == InterfaceSignature_ERC165) || (_interfaceID == InterfaceSignature_ERC721)); + } + + /// @dev Set the address of the sibling contract that tracks metadata. + /// CEO only. + function setMetadataAddress(address _contractAddress) public onlyCEO { + erc721Metadata = ERC721Metadata(_contractAddress); + } + + // Internal utility functions: These functions all assume that their input arguments + // are valid. We leave it to public methods to sanitize their inputs and follow + // the required logic. + + /// @dev Checks if a given address is the current owner of a particular Kitty. + /// @param _claimant the address we are validating against. + /// @param _tokenId kitten id, only valid when > 0 + function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { + return kittyIndexToOwner[_tokenId] == _claimant; + } + + /// @dev Checks if a given address currently has transferApproval for a particular Kitty. + /// @param _claimant the address we are confirming kitten is approved for. + /// @param _tokenId kitten id, only valid when > 0 + function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) { + return kittyIndexToApproved[_tokenId] == _claimant; + } + + /// @dev Marks an address as being approved for transferFrom(), overwriting any previous + /// approval. Setting _approved to address(0) clears all transfer approval. + /// NOTE: _approve() does NOT send the Approval event. This is intentional because + /// _approve() and transferFrom() are used together for putting Kitties on auction, and + /// there is no value in spamming the log with Approval events in that case. + function _approve(uint256 _tokenId, address _approved) internal { + kittyIndexToApproved[_tokenId] = _approved; + } + + /// @notice Returns the number of Kitties owned by a specific address. + /// @param _owner The owner address to check. + /// @dev Required for ERC-721 compliance + function balanceOf(address _owner) public view returns (uint256 count) { + return ownershipTokenCount[_owner]; + } + + /// @notice Transfers a Kitty to another address. If transferring to a smart + /// contract be VERY CAREFUL to ensure that it is aware of ERC-721 (or + /// CryptoKitties specifically) or your Kitty may be lost forever. Seriously. + /// @param _to The address of the recipient, can be a user or contract. + /// @param _tokenId The ID of the Kitty to transfer. + /// @dev Required for ERC-721 compliance. + function transfer( + address _to, + uint256 _tokenId + ) + external + whenNotPaused + { + // Safety check to prevent against an unexpected 0x0 default. + require(_to != address(0)); + // Disallow transfers to this contract to prevent accidental misuse. + // The contract should never own any kitties (except very briefly + // after a gen0 cat is created and before it goes on auction). + require(_to != address(this)); + // Disallow transfers to the auction contracts to prevent accidental + // misuse. Auction contracts should only take ownership of kitties + // through the allow + transferFrom flow. + require(_to != address(saleAuction)); + require(_to != address(siringAuction)); + + // You can only send your own cat. + require(_owns(msg.sender, _tokenId)); + + // Reassign ownership, clear pending approvals, emit Transfer event. + _transfer(msg.sender, _to, _tokenId); + } + + /// @notice Grant another address the right to transfer a specific Kitty via + /// transferFrom(). This is the preferred flow for transfering NFTs to contracts. + /// @param _to The address to be granted transfer approval. Pass address(0) to + /// clear all approvals. + /// @param _tokenId The ID of the Kitty that can be transferred if this call succeeds. + /// @dev Required for ERC-721 compliance. + function approve( + address _to, + uint256 _tokenId + ) + external + whenNotPaused + { + // Only an owner can grant transfer approval. + require(_owns(msg.sender, _tokenId)); + + // Register the approval (replacing any previous approval). + _approve(_tokenId, _to); + + // Emit approval event. + emit Approval(msg.sender, _to, _tokenId); + } + + /// @notice Transfer a Kitty owned by another address, for which the calling address + /// has previously been granted transfer approval by the owner. + /// @param _from The address that owns the Kitty to be transfered. + /// @param _to The address that should take ownership of the Kitty. Can be any address, + /// including the caller. + /// @param _tokenId The ID of the Kitty to be transferred. + /// @dev Required for ERC-721 compliance. + function transferFrom( + address _from, + address _to, + uint256 _tokenId + ) + external + whenNotPaused + { + // Safety check to prevent against an unexpected 0x0 default. + require(_to != address(0)); + // Disallow transfers to this contract to prevent accidental misuse. + // The contract should never own any kitties (except very briefly + // after a gen0 cat is created and before it goes on auction). + require(_to != address(this)); + // Check for approval and valid ownership + require(_approvedFor(msg.sender, _tokenId)); + require(_owns(_from, _tokenId)); + + // Reassign ownership (also clears pending approvals and emits Transfer event). + _transfer(_from, _to, _tokenId); + } + + /// @notice Returns the total number of Kitties currently in existence. + /// @dev Required for ERC-721 compliance. + function totalSupply() public view returns (uint) { + return kitties.length - 1; + } + + /// @notice Returns the address currently assigned ownership of a given Kitty. + /// @dev Required for ERC-721 compliance. + function ownerOf(uint256 _tokenId) + external + view + returns (address owner) + { + owner = kittyIndexToOwner[_tokenId]; + + require(owner != address(0)); + } + + /// @notice Returns a list of all Kitty IDs assigned to an address. + /// @param _owner The owner whose Kitties we are interested in. + /// @dev This method MUST NEVER be called by smart contract code. First, it's fairly + /// expensive (it walks the entire Kitty array looking for cats belonging to owner), + /// but it also returns a dynamic array, which is only supported for web3 calls, and + /// not contract-to-contract calls. + function tokensOfOwner(address _owner) external view returns(uint256[] memory ownerTokens) { + uint256 tokenCount = balanceOf(_owner); + + if (tokenCount == 0) { + // Return an empty array + return new uint256[](0); + } else { + uint256[] memory result = new uint256[](tokenCount); + uint256 totalCats = totalSupply(); + uint256 resultIndex = 0; + + // We count on the fact that all cats have IDs starting at 1 and increasing + // sequentially up to the totalCat count. + uint256 catId; + + for (catId = 1; catId <= totalCats; catId++) { + if (kittyIndexToOwner[catId] == _owner) { + result[resultIndex] = catId; + resultIndex++; + } + } + + return result; + } + } + + /// @dev Adapted from memcpy() by @arachnid (Nick Johnson ) + /// This method is licenced under the Apache License. + /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol + function _memcpy(uint _dest, uint _src, uint _len) private view { + // Copy word-length chunks while possible + for(; _len >= 32; _len -= 32) { + assembly { + mstore(_dest, mload(_src)) + } + _dest += 32; + _src += 32; + } + + // Copy remaining bytes + uint256 mask = 256 ** (32 - _len) - 1; + assembly { + let srcpart := and(mload(_src), not(mask)) + let destpart := and(mload(_dest), mask) + mstore(_dest, or(destpart, srcpart)) + } + } + + /// @dev Adapted from toString(slice) by @arachnid (Nick Johnson ) + /// This method is licenced under the Apache License. + /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol + function _toString(bytes32[4] memory _rawBytes, uint256 _stringLength) private view returns (string memory) { + string memory outputString = new string(_stringLength); + uint256 outputPtr; + uint256 bytesPtr; + + assembly { + outputPtr := add(outputString, 32) + bytesPtr := _rawBytes + } + + _memcpy(outputPtr, bytesPtr, _stringLength); + + return outputString; + } + + /// @notice Returns a URI pointing to a metadata package for this token conforming to + /// ERC-721 (https://github.com/ethereum/EIPs/issues/721) + /// @param _tokenId The ID number of the Kitty whose metadata should be returned. + function tokenMetadata(uint256 _tokenId, string calldata _preferredTransport) external view returns (string memory infoUrl) { + require( address(erc721Metadata) != address(0)); + bytes32[4] memory buffer; + uint256 count; + (buffer, count) = erc721Metadata.getMetadata(_tokenId, _preferredTransport); + + return _toString(buffer, count); + } +} + + + + +/// @title A facet of KittyCore that manages Kitty siring, gestation, and birth. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. +contract KittyBreeding is KittyOwnership { + + /// @dev The Pregnant event is fired when two cats successfully breed and the pregnancy + /// timer begins for the matron. + event Pregnant(address owner, uint256 matronId, uint256 sireId, uint256 cooldownEndBlock); + + /// @notice The minimum payment required to use breedWithAuto(). This fee goes towards + /// the gas cost paid by whatever calls giveBirth(), and can be dynamically updated by + /// the COO role as the gas price changes. + uint256 public autoBirthFee = 2 sun; + + // Keeps track of number of pregnant kitties. + uint256 public pregnantKitties; + + /// @dev The address of the sibling contract that is used to implement the sooper-sekret + /// genetic combination algorithm. + GeneScienceInterface public geneScience; + + /// @dev Update the address of the genetic contract, can only be called by the CEO. + /// @param _address An address of a GeneScience contract instance to be used from this point forward. + function setGeneScienceAddress(address _address) external onlyCEO { + GeneScienceInterface candidateContract = GeneScienceInterface(_address); + + // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 + require(candidateContract.isGeneScience()); + + // Set the new contract address + geneScience = candidateContract; + } + + /// @dev Checks that a given kitten is able to breed. Requires that the + /// current cooldown is finished (for sires) and also checks that there is + /// no pending pregnancy. + function _isReadyToBreed(Kitty memory _kit) internal view returns (bool) { + // In addition to checking the cooldownEndBlock, we also need to check to see if + // the cat has a pending birth; there can be some period of time between the end + // of the pregnacy timer and the birth event. + return (_kit.siringWithId == 0) && (_kit.cooldownEndBlock <= uint64(block.number)); + } + + /// @dev Check if a sire has authorized breeding with this matron. True if both sire + /// and matron have the same owner, or if the sire has given siring permission to + /// the matron's owner (via approveSiring()). + function _isSiringPermitted(uint256 _sireId, uint256 _matronId) internal view returns (bool) { + address matronOwner = kittyIndexToOwner[_matronId]; + address sireOwner = kittyIndexToOwner[_sireId]; + + // Siring is okay if they have same owner, or if the matron's owner was given + // permission to breed with this sire. + return (matronOwner == sireOwner || sireAllowedToAddress[_sireId] == matronOwner); + } + + /// @dev Set the cooldownEndTime for the given Kitty, based on its current cooldownIndex. + /// Also increments the cooldownIndex (unless it has hit the cap). + /// @param _kitten A reference to the Kitty in storage which needs its timer started. + function _triggerCooldown(Kitty storage _kitten) internal { + // Compute an estimation of the cooldown time in blocks (based on current cooldownIndex). + _kitten.cooldownEndBlock = uint64((cooldowns[_kitten.cooldownIndex]/secondsPerBlock) + block.number); + + // Increment the breeding count, clamping it at 13, which is the length of the + // cooldowns array. We could check the array size dynamically, but hard-coding + // this as a constant saves gas. Yay, Solidity! + if (_kitten.cooldownIndex < 13) { + _kitten.cooldownIndex += 1; + } + } + + /// @notice Grants approval to another user to sire with one of your Kitties. + /// @param _addr The address that will be able to sire with your Kitty. Set to + /// address(0) to clear all siring approvals for this Kitty. + /// @param _sireId A Kitty that you own that _addr will now be able to sire with. + function approveSiring(address _addr, uint256 _sireId) + external + whenNotPaused + { + require(_owns(msg.sender, _sireId)); + sireAllowedToAddress[_sireId] = _addr; + } + + /// @dev Updates the minimum payment required for calling giveBirthAuto(). Can only + /// be called by the COO address. (This fee is used to offset the gas cost incurred + /// by the autobirth daemon). + function setAutoBirthFee(uint256 val) external onlyCOO { + autoBirthFee = val; + } + + /// @dev Checks to see if a given Kitty is pregnant and (if so) if the gestation + /// period has passed. + function _isReadyToGiveBirth(Kitty memory _matron) private view returns (bool) { + return (_matron.siringWithId != 0) && (_matron.cooldownEndBlock <= uint64(block.number)); + } + + /// @notice Checks that a given kitten is able to breed (i.e. it is not pregnant or + /// in the middle of a siring cooldown). + /// @param _kittyId reference the id of the kitten, any user can inquire about it + function isReadyToBreed(uint256 _kittyId) + public + view + returns (bool) + { + require(_kittyId > 0); + Kitty storage kit = kitties[_kittyId]; + return _isReadyToBreed(kit); + } + + /// @dev Checks whether a kitty is currently pregnant. + /// @param _kittyId reference the id of the kitten, any user can inquire about it + function isPregnant(uint256 _kittyId) + public + view + returns (bool) + { + require(_kittyId > 0); + // A kitty is pregnant if and only if this field is set + return kitties[_kittyId].siringWithId != 0; + } + + /// @dev Internal check to see if a given sire and matron are a valid mating pair. DOES NOT + /// check ownership permissions (that is up to the caller). + /// @param _matron A reference to the Kitty struct of the potential matron. + /// @param _matronId The matron's ID. + /// @param _sire A reference to the Kitty struct of the potential sire. + /// @param _sireId The sire's ID + function _isValidMatingPair( + Kitty storage _matron, + uint256 _matronId, + Kitty storage _sire, + uint256 _sireId + ) + private + view + returns(bool) + { + // A Kitty can't breed with itself! + if (_matronId == _sireId) { + return false; + } + + // Kitties can't breed with their parents. + if (_matron.matronId == _sireId || _matron.sireId == _sireId) { + return false; + } + if (_sire.matronId == _matronId || _sire.sireId == _matronId) { + return false; + } + + // We can short circuit the sibling check (below) if either cat is + // gen zero (has a matron ID of zero). + if (_sire.matronId == 0 || _matron.matronId == 0) { + return true; + } + + // Kitties can't breed with full or half siblings. + if (_sire.matronId == _matron.matronId || _sire.matronId == _matron.sireId) { + return false; + } + if (_sire.sireId == _matron.matronId || _sire.sireId == _matron.sireId) { + return false; + } + + // Everything seems cool! Let's get DTF. + return true; + } + + /// @dev Internal check to see if a given sire and matron are a valid mating pair for + /// breeding via auction (i.e. skips ownership and siring approval checks). + function _canBreedWithViaAuction(uint256 _matronId, uint256 _sireId) + internal + view + returns (bool) + { + Kitty storage matron = kitties[_matronId]; + Kitty storage sire = kitties[_sireId]; + return _isValidMatingPair(matron, _matronId, sire, _sireId); + } + + /// @notice Checks to see if two cats can breed together, including checks for + /// ownership and siring approvals. Does NOT check that both cats are ready for + /// breeding (i.e. breedWith could still fail until the cooldowns are finished). + /// TODO: Shouldn't this check pregnancy and cooldowns?!? + /// @param _matronId The ID of the proposed matron. + /// @param _sireId The ID of the proposed sire. + function canBreedWith(uint256 _matronId, uint256 _sireId) + external + view + returns(bool) + { + require(_matronId > 0); + require(_sireId > 0); + Kitty storage matron = kitties[_matronId]; + Kitty storage sire = kitties[_sireId]; + return _isValidMatingPair(matron, _matronId, sire, _sireId) && + _isSiringPermitted(_sireId, _matronId); + } + + /// @dev Internal utility function to initiate breeding, assumes that all breeding + /// requirements have been checked. + function _breedWith(uint256 _matronId, uint256 _sireId) internal { + // Grab a reference to the Kitties from storage. + Kitty storage sire = kitties[_sireId]; + Kitty storage matron = kitties[_matronId]; + + // Mark the matron as pregnant, keeping track of who the sire is. + matron.siringWithId = uint32(_sireId); + + // Trigger the cooldown for both parents. + _triggerCooldown(sire); + _triggerCooldown(matron); + + // Clear siring permission for both parents. This may not be strictly necessary + // but it's likely to avoid confusion! + delete sireAllowedToAddress[_matronId]; + delete sireAllowedToAddress[_sireId]; + + // Every time a kitty gets pregnant, counter is incremented. + pregnantKitties++; + + // Emit the pregnancy event. + emit Pregnant(kittyIndexToOwner[_matronId], _matronId, _sireId, matron.cooldownEndBlock); + } + + /// @notice Breed a Kitty you own (as matron) with a sire that you own, or for which you + /// have previously been given Siring approval. Will either make your cat pregnant, or will + /// fail entirely. Requires a pre-payment of the fee given out to the first caller of giveBirth() + /// @param _matronId The ID of the Kitty acting as matron (will end up pregnant if successful) + /// @param _sireId The ID of the Kitty acting as sire (will begin its siring cooldown if successful) + function breedWithAuto(uint256 _matronId, uint256 _sireId) + external + payable + whenNotPaused + { + // Checks for payment. + require(msg.value >= autoBirthFee); + + // Caller must own the matron. + require(_owns(msg.sender, _matronId)); + + // Neither sire nor matron are allowed to be on auction during a normal + // breeding operation, but we don't need to check that explicitly. + // For matron: The caller of this function can't be the owner of the matron + // because the owner of a Kitty on auction is the auction house, and the + // auction house will never call breedWith(). + // For sire: Similarly, a sire on auction will be owned by the auction house + // and the act of transferring ownership will have cleared any oustanding + // siring approval. + // Thus we don't need to spend gas explicitly checking to see if either cat + // is on auction. + + // Check that matron and sire are both owned by caller, or that the sire + // has given siring permission to caller (i.e. matron's owner). + // Will fail for _sireId = 0 + require(_isSiringPermitted(_sireId, _matronId)); + + // Grab a reference to the potential matron + Kitty storage matron = kitties[_matronId]; + + // Make sure matron isn't pregnant, or in the middle of a siring cooldown + require(_isReadyToBreed(matron)); + + // Grab a reference to the potential sire + Kitty storage sire = kitties[_sireId]; + + // Make sure sire isn't pregnant, or in the middle of a siring cooldown + require(_isReadyToBreed(sire)); + + // Test that these cats are a valid mating pair. + require(_isValidMatingPair( + matron, + _matronId, + sire, + _sireId + )); + + // All checks passed, kitty gets pregnant! + _breedWith(_matronId, _sireId); + } + + /// @notice Have a pregnant Kitty give birth! + /// @param _matronId A Kitty ready to give birth. + /// @return The Kitty ID of the new kitten. + /// @dev Looks at a given Kitty and, if pregnant and if the gestation period has passed, + /// combines the genes of the two parents to create a new kitten. The new Kitty is assigned + /// to the current owner of the matron. Upon successful completion, both the matron and the + /// new kitten will be ready to breed again. Note that anyone can call this function (if they + /// are willing to pay the gas!), but the new kitten always goes to the mother's owner. + function giveBirth(uint256 _matronId) + external + whenNotPaused + returns(uint256) + { + // Grab a reference to the matron in storage. + Kitty storage matron = kitties[_matronId]; + + // Check that the matron is a valid cat. + require(matron.birthTime != 0); + + // Check that the matron is pregnant, and that its time has come! + require(_isReadyToGiveBirth(matron)); + + // Grab a reference to the sire in storage. + uint256 sireId = matron.siringWithId; + Kitty storage sire = kitties[sireId]; + + // Determine the higher generation number of the two parents + uint16 parentGen = matron.generation; + if (sire.generation > matron.generation) { + parentGen = sire.generation; + } + + // Call the sooper-sekret gene mixing operation. + uint256 childGenes = geneScience.mixGenes(matron.genes, sire.genes, matron.cooldownEndBlock - 1); + + // Make the new kitten! + address owner = kittyIndexToOwner[_matronId]; + uint256 kittenId = _createKitty(_matronId, matron.siringWithId, parentGen + 1, childGenes, owner); + + // Clear the reference to sire from the matron (REQUIRED! Having siringWithId + // set is what marks a matron as being pregnant.) + delete matron.siringWithId; + + // Every time a kitty gives birth counter is decremented. + pregnantKitties--; + + // Send the balance fee to the person who made birth happen. + msg.sender.transfer(autoBirthFee); + + // return the new kitten's ID + return kittenId; + } +} + + + +/// @title Handles creating auctions for sale and siring of kitties. +/// This wrapper of ReverseAuction exists only so that users can create +/// auctions with only one transaction. +contract KittyAuction is KittyBreeding { + + // @notice The auction contract variables are defined in KittyBase to allow + // us to refer to them in KittyOwnership to prevent accidental transfers. + // `saleAuction` refers to the auction for gen0 and p2p sale of kitties. + // `siringAuction` refers to the auction for siring rights of kitties. + + /// @dev Sets the reference to the sale auction. + /// @param _address - Address of sale contract. + function setSaleAuctionAddress(address _address) external onlyCEO { + SaleClockAuction candidateContract = SaleClockAuction(_address); + + // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 + require(candidateContract.isSaleClockAuction()); + + // Set the new contract address + saleAuction = candidateContract; + } + + /// @dev Sets the reference to the siring auction. + /// @param _address - Address of siring contract. + function setSiringAuctionAddress(address _address) external onlyCEO { + SiringClockAuction candidateContract = SiringClockAuction(_address); + + // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 + require(candidateContract.isSiringClockAuction()); + + // Set the new contract address + siringAuction = candidateContract; + } + + /// @dev Put a kitty up for auction. + /// Does some ownership trickery to create auctions in one tx. + function createSaleAuction( + uint256 _kittyId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration + ) + external + whenNotPaused + { + // Auction contract checks input sizes + // If kitty is already on any auction, this will throw + // because it will be owned by the auction contract. + require(_owns(msg.sender, _kittyId)); + // Ensure the kitty is not pregnant to prevent the auction + // contract accidentally receiving ownership of the child. + // NOTE: the kitty IS allowed to be in a cooldown. + require(!isPregnant(_kittyId)); + _approve(_kittyId, address(saleAuction)); + // Sale auction throws if inputs are invalid and clears + // transfer and sire approval after escrowing the kitty. + saleAuction.createAuction( + _kittyId, + _startingPrice, + _endingPrice, + _duration, + msg.sender + ); + } + + /// @dev Put a kitty up for auction to be sire. + /// Performs checks to ensure the kitty can be sired, then + /// delegates to reverse auction. + function createSiringAuction( + uint256 _kittyId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration + ) + external + whenNotPaused + { + // Auction contract checks input sizes + // If kitty is already on any auction, this will throw + // because it will be owned by the auction contract. + require(_owns(msg.sender, _kittyId)); + require(isReadyToBreed(_kittyId)); + _approve(_kittyId, address(siringAuction)); + // Siring auction throws if inputs are invalid and clears + // transfer and sire approval after escrowing the kitty. + siringAuction.createAuction( + _kittyId, + _startingPrice, + _endingPrice, + _duration, + msg.sender + ); + } + + /// @dev Completes a siring auction by bidding. + /// Immediately breeds the winning matron with the sire on auction. + /// @param _sireId - ID of the sire on auction. + /// @param _matronId - ID of the matron owned by the bidder. + function bidOnSiringAuction( + uint256 _sireId, + uint256 _matronId + ) + external + payable + whenNotPaused + { + // Auction contract checks input sizes + require(_owns(msg.sender, _matronId)); + require(isReadyToBreed(_matronId)); + require(_canBreedWithViaAuction(_matronId, _sireId)); + + // Define the current price of the auction. + uint256 currentPrice = siringAuction.getCurrentPrice(_sireId); + require(msg.value >= currentPrice + autoBirthFee); + + // Siring auction will throw if the bid fails. + siringAuction.bid.value(msg.value - autoBirthFee)(_sireId); + _breedWith(uint32(_matronId), uint32(_sireId)); + } + + /// @dev Transfers the balance of the sale auction contract + /// to the KittyCore contract. We use two-step withdrawal to + /// prevent two transfer calls in the auction bid function. + function withdrawAuctionBalances() external onlyCLevel { + saleAuction.withdrawBalance(); + siringAuction.withdrawBalance(); + } +} + + +/// @title all functions related to creating kittens +contract KittyMinting is KittyAuction { + + // Limits the number of cats the contract owner can ever create. + uint256 public constant PROMO_CREATION_LIMIT = 5000; + uint256 public constant GEN0_CREATION_LIMIT = 45000; + + // Constants for gen0 auctions. + uint256 public constant GEN0_STARTING_PRICE = 10 sun; + uint256 public constant GEN0_AUCTION_DURATION = 1 days; + + // Counts the number of cats the contract owner has created. + uint256 public promoCreatedCount; + uint256 public gen0CreatedCount; + + /// @dev we can create promo kittens, up to a limit. Only callable by COO + /// @param _genes the encoded genes of the kitten to be created, any value is accepted + /// @param _owner the future owner of the created kittens. Default to contract COO + function createPromoKitty(uint256 _genes, address _owner) external onlyCOO { + address kittyOwner = _owner; + if (kittyOwner == address(0)) { + kittyOwner = cooAddress; + } + require(promoCreatedCount < PROMO_CREATION_LIMIT); + + promoCreatedCount++; + _createKitty(0, 0, 0, _genes, kittyOwner); + } + + /// @dev Creates a new gen0 kitty with the given genes and + /// creates an auction for it. + function createGen0Auction(uint256 _genes) external onlyCOO { + require(gen0CreatedCount < GEN0_CREATION_LIMIT); + + uint256 kittyId = _createKitty(0, 0, 0, _genes, address(this)); + _approve(kittyId, address(saleAuction)); + + saleAuction.createAuction( + kittyId, + _computeNextGen0Price(), + 0, + GEN0_AUCTION_DURATION, + address(uint160(address(this))) + ); + + gen0CreatedCount++; + } + + /// @dev Computes the next gen0 auction starting price, given + /// the average of the past 5 prices + 50%. + function _computeNextGen0Price() internal view returns (uint256) { + uint256 avePrice = saleAuction.averageGen0SalePrice(); + + // Sanity check to ensure we don't overflow arithmetic + require(avePrice == uint256(uint128(avePrice))); + + uint256 nextPrice = avePrice + (avePrice / 2); + + // We never auction for less than starting price + if (nextPrice < GEN0_STARTING_PRICE) { + nextPrice = GEN0_STARTING_PRICE; + } + + return nextPrice; + } +} + + + +/// @title CryptoKitties: Collectible, breedable, and oh-so-adorable cats on the Ethereum blockchain. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev The main CryptoKitties contract, keeps track of kittens so they don't wander around and get lost. +contract KittyCore is KittyMinting { + + // This is the main CryptoKitties contract. In order to keep our code seperated into logical sections, + // we've broken it up in two ways. First, we have several seperately-instantiated sibling contracts + // that handle auctions and our super-top-secret genetic combination algorithm. The auctions are + // seperate since their logic is somewhat complex and there's always a risk of subtle bugs. By keeping + // them in their own contracts, we can upgrade them without disrupting the main contract that tracks + // kitty ownership. The genetic combination algorithm is kept seperate so we can open-source all of + // the rest of our code without making it _too_ easy for folks to figure out how the genetics work. + // Don't worry, I'm sure someone will reverse engineer it soon enough! + // + // Secondly, we break the core contract into multiple files using inheritence, one for each major + // facet of functionality of CK. This allows us to keep related code bundled together while still + // avoiding a single giant file with everything in it. The breakdown is as follows: + // + // - KittyBase: This is where we define the most fundamental code shared throughout the core + // functionality. This includes our main data storage, constants and data types, plus + // internal functions for managing these items. + // + // - KittyAccessControl: This contract manages the various addresses and constraints for operations + // that can be executed only by specific roles. Namely CEO, CFO and COO. + // + // - KittyOwnership: This provides the methods required for basic non-fungible token + // transactions, following the draft ERC-721 spec (https://github.com/ethereum/EIPs/issues/721). + // + // - KittyBreeding: This file contains the methods necessary to breed cats together, including + // keeping track of siring offers, and relies on an external genetic combination contract. + // + // - KittyAuctions: Here we have the public methods for auctioning or bidding on cats or siring + // services. The actual auction functionality is handled in two sibling contracts (one + // for sales and one for siring), while auction creation and bidding is mostly mediated + // through this facet of the core contract. + // + // - KittyMinting: This final facet contains the functionality we use for creating new gen0 cats. + // We can make up to 5000 "promo" cats that can be given away (especially important when + // the community is new), and all others can only be created and then immediately put up + // for auction via an algorithmically determined starting price. Regardless of how they + // are created, there is a hard limit of 50k gen0 cats. After that, it's all up to the + // community to breed, breed, breed! + + // Set in case the core contract is broken and an upgrade is required + address public newContractAddress; + + /// @notice Creates the main CryptoKitties smart contract instance. + constructor() public { + // Starts paused. + paused = true; + + // the creator of the contract is the initial CEO + ceoAddress = msg.sender; + + // the creator of the contract is also the initial COO + cooAddress = msg.sender; + + // start with the mythical kitten 0 - so we don't have generation-0 parent issues + _createKitty(0, 0, 0, uint256(-1), address(0)); + } + + /// @dev Used to mark the smart contract as upgraded, in case there is a serious + /// breaking bug. This method does nothing but keep track of the new contract and + /// emit a message indicating that the new address is set. It's up to clients of this + /// contract to update to the new contract address in that case. (This contract will + /// be paused indefinitely if such an upgrade takes place.) + /// @param _v2Address new address + function setNewAddress(address _v2Address) external onlyCEO whenPaused { + // See README.md for updgrade plan + newContractAddress = _v2Address; + emit ContractUpgrade(_v2Address); + } + + /// @notice No tipping! + /// @dev Reject all Ether from being sent here, unless it's from one of the + /// two auction contracts. (Hopefully, we can prevent user accidents.) + function() external payable { + require( + msg.sender == address(saleAuction) || + msg.sender == address(siringAuction) + ); + } + + /// @notice Returns all the relevant information about a specific kitty. + /// @param _id The ID of the kitty of interest. + function getKitty(uint256 _id) + external + view + returns ( + bool isGestating, + bool isReady, + uint256 cooldownIndex, + uint256 nextActionAt, + uint256 siringWithId, + uint256 birthTime, + uint256 matronId, + uint256 sireId, + uint256 generation, + uint256 genes + ) { + Kitty storage kit = kitties[_id]; + + // if this variable is 0 then it's not gestating + isGestating = (kit.siringWithId != 0); + isReady = (kit.cooldownEndBlock <= block.number); + cooldownIndex = uint256(kit.cooldownIndex); + nextActionAt = uint256(kit.cooldownEndBlock); + siringWithId = uint256(kit.siringWithId); + birthTime = uint256(kit.birthTime); + matronId = uint256(kit.matronId); + sireId = uint256(kit.sireId); + generation = uint256(kit.generation); + genes = kit.genes; + } + + /// @dev Override unpause so it requires all external contract addresses + /// to be set before contract can be unpaused. Also, we can't have + /// newContractAddress set either, because then the contract was upgraded. + /// @notice This is public rather than external so we can call super.unpause + /// without using an expensive CALL. + + function unpause() public onlyCEO whenPaused { + require(address(saleAuction) != address(0)); + require(address(siringAuction) != address(0)); + require(address(geneScience) != address(0)); + require(newContractAddress == address(0)); + + // Actually unpause the contract. + super.unpause(); + } + + // @dev Allows the CFO to capture the balance available to the contract. + function withdrawBalance() external onlyCFO { + uint256 balance = address(this).balance; + // Subtract all the currently pregnant kittens we have, plus 1 of margin. + uint256 subtractFees = (pregnantKitties + 1) * autoBirthFee; + + if (balance > subtractFees) { + cfoAddress.transfer(balance - subtractFees); + } + } +} + + + + + + + + + + + + + +// // Auction wrapper functions + + +// Auction wrapper functions + + + + + + + +/// @title SEKRETOOOO +contract GeneScienceInterface { + + function isGeneScience() public pure returns (bool){ + return true; + } + + /// @dev given genes of kitten 1 & 2, return a genetic combination - may have a random factor + /// @param genes1 genes of mom + /// @param genes2 genes of sire + /// @return the genes that are supposed to be passed down the child + function mixGenes(uint256 genes1, uint256 genes2, uint256 targetBlock) public pure returns (uint256){ + + return (genes1+genes2+targetBlock)/2; + + +} +} + + + + + + + + + + + + + + + + +/// @title The external contract that is responsible for generating metadata for the kitties, +/// it has one function that will return the data as bytes. +contract ERC721Metadata { + /// @dev Given a token Id, returns a byte array that is supposed to be converted into string. + function getMetadata(uint256 _tokenId, string memory) public view returns (bytes32[4] memory buffer, uint256 count) { + if (_tokenId == 1) { + buffer[0] = "Hello World! :D"; + count = 15; + } else if (_tokenId == 2) { + buffer[0] = "I would definitely choose a medi"; + buffer[1] = "um length string."; + count = 49; + } else if (_tokenId == 3) { + buffer[0] = "Lorem ipsum dolor sit amet, mi e"; + buffer[1] = "st accumsan dapibus augue lorem,"; + buffer[2] = " tristique vestibulum id, libero"; + buffer[3] = " suscipit varius sapien aliquam."; + count = 128; + } + } +} + + + + + + + + + + + + + + + +/// @title Auction Core +/// @dev Contains models, variables, and internal methods for the auction. +/// @notice We omit a fallback function to prevent accidental sends to this contract. +contract ClockAuctionBase { + + // Represents an auction on an NFT + struct Auction { + // Current owner of NFT + address payable seller; + // Price (in wei) at beginning of auction + uint128 startingPrice; + // Price (in wei) at end of auction + uint128 endingPrice; + // Duration (in seconds) of auction + uint64 duration; + // Time when auction started + // NOTE: 0 if this auction has been concluded + uint64 startedAt; + } + + // Reference to contract tracking NFT ownership + ERC721 public nonFungibleContract; + + // Cut owner takes on each auction, measured in basis points (1/100 of a percent). + // Values 0-10,000 map to 0%-100% + uint256 public ownerCut; + + // Map from token ID to their corresponding auction. + mapping (uint256 => Auction) tokenIdToAuction; + + event AuctionCreated(uint256 tokenId, uint256 startingPrice, uint256 endingPrice, uint256 duration); + event AuctionSuccessful(uint256 tokenId, uint256 totalPrice, address winner); + event AuctionCancelled(uint256 tokenId); + + /// @dev Returns true if the claimant owns the token. + /// @param _claimant - Address claiming to own the token. + /// @param _tokenId - ID of token whose ownership to verify. + function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { + return (nonFungibleContract.ownerOf(_tokenId) == _claimant); + } + + /// @dev Escrows the NFT, assigning ownership to this contract. + /// Throws if the escrow fails. + /// @param _owner - Current owner address of token to escrow. + /// @param _tokenId - ID of token whose approval to verify. + function _escrow(address _owner, uint256 _tokenId) internal { + // it will throw if transfer fails + nonFungibleContract.transferFrom(_owner, address(this), _tokenId); + } + + /// @dev Transfers an NFT owned by this contract to another address. + /// Returns true if the transfer succeeds. + /// @param _receiver - Address to transfer NFT to. + /// @param _tokenId - ID of token to transfer. + function _transfer(address _receiver, uint256 _tokenId) internal { + // it will throw if transfer fails + nonFungibleContract.transfer(_receiver, _tokenId); + } + + /// @dev Adds an auction to the list of open auctions. Also fires the + /// AuctionCreated event. + /// @param _tokenId The ID of the token to be put on auction. + /// @param _auction Auction to add. + function _addAuction(uint256 _tokenId, Auction memory _auction) internal { + // Require that all auctions have a duration of + // at least one minute. (Keeps our math from getting hairy!) + require(_auction.duration >= 1 minutes); + + tokenIdToAuction[_tokenId] = _auction; + + emit AuctionCreated( + uint256(_tokenId), + uint256(_auction.startingPrice), + uint256(_auction.endingPrice), + uint256(_auction.duration) + ); + } + + /// @dev Cancels an auction unconditionally. + function _cancelAuction(uint256 _tokenId, address _seller) internal { + _removeAuction(_tokenId); + _transfer(_seller, _tokenId); + emit AuctionCancelled(_tokenId); + } + + /// @dev Computes the price and transfers winnings. + /// Does NOT transfer ownership of token. + function _bid(uint256 _tokenId, uint256 _bidAmount) + internal + returns (uint256) + { + // Get a reference to the auction struct + Auction storage auction = tokenIdToAuction[_tokenId]; + + // Explicitly check that this auction is currently live. + // (Because of how Ethereum mappings work, we can't just count + // on the lookup above failing. An invalid _tokenId will just + // return an auction object that is all zeros.) + require(_isOnAuction(auction)); + + // Check that the bid is greater than or equal to the current price + uint256 price = _currentPrice(auction); + require(_bidAmount >= price); + + // Grab a reference to the seller before the auction struct + // gets deleted. + address payable seller = auction.seller; + + // The bid is good! Remove the auction before sending the fees + // to the sender so we can't have a reentrancy attack. + _removeAuction(_tokenId); + + // Transfer proceeds to seller (if there are any!) + if (price > 0) { + // Calculate the auctioneer's cut. + // (NOTE: _computeCut() is guaranteed to return a + // value <= price, so this subtraction can't go negative.) + uint256 auctioneerCut = _computeCut(price); + uint256 sellerProceeds = price - auctioneerCut; + + // NOTE: Doing a transfer() in the middle of a complex + // method like this is generally discouraged because of + // reentrancy attacks and DoS attacks if the seller is + // a contract with an invalid fallback function. We explicitly + // guard against reentrancy attacks by removing the auction + // before calling transfer(), and the only thing the seller + // can DoS is the sale of their own asset! (And if it's an + // accident, they can call cancelAuction(). ) + seller.transfer(sellerProceeds); + } + + // Calculate any excess funds included with the bid. If the excess + // is anything worth worrying about, transfer it back to bidder. + // NOTE: We checked above that the bid amount is greater than or + // equal to the price so this cannot underflow. + uint256 bidExcess = _bidAmount - price; + + // Return the funds. Similar to the previous transfer, this is + // not susceptible to a re-entry attack because the auction is + // removed before any transfers occur. + msg.sender.transfer(bidExcess); + + // Tell the world! + emit AuctionSuccessful(_tokenId, price, msg.sender); + + return price; + } + + /// @dev Removes an auction from the list of open auctions. + /// @param _tokenId - ID of NFT on auction. + function _removeAuction(uint256 _tokenId) internal { + delete tokenIdToAuction[_tokenId]; + } + + /// @dev Returns true if the NFT is on auction. + /// @param _auction - Auction to check. + function _isOnAuction(Auction storage _auction) internal view returns (bool) { + return (_auction.startedAt > 0); + } + + /// @dev Returns current price of an NFT on auction. Broken into two + /// functions (this one, that computes the duration from the auction + /// structure, and the other that does the price computation) so we + /// can easily test that the price computation works correctly. + function _currentPrice(Auction storage _auction) + internal + view + returns (uint256) + { + uint256 secondsPassed = 0; + + // A bit of insurance against negative values (or wraparound). + // Probably not necessary (since Ethereum guarnatees that the + // now variable doesn't ever go backwards). + if (now > _auction.startedAt) { + secondsPassed = now - _auction.startedAt; + } + + return _computeCurrentPrice( + _auction.startingPrice, + _auction.endingPrice, + _auction.duration, + secondsPassed + ); + } + + /// @dev Computes the current price of an auction. Factored out + /// from _currentPrice so we can run extensive unit tests. + /// When testing, make this function public and turn on + /// `Current price computation` test suite. + function _computeCurrentPrice( + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration, + uint256 _secondsPassed + ) + internal + pure + returns (uint256) + { + // NOTE: We don't use SafeMath (or similar) in this function because + // all of our public functions carefully cap the maximum values for + // time (at 64-bits) and currency (at 128-bits). _duration is + // also known to be non-zero (see the require() statement in + // _addAuction()) + if (_secondsPassed >= _duration) { + // We've reached the end of the dynamic pricing portion + // of the auction, just return the end price. + return _endingPrice; + } else { + // Starting price can be higher than ending price (and often is!), so + // this delta can be negative. + int256 totalPriceChange = int256(_endingPrice) - int256(_startingPrice); + + // This multiplication can't overflow, _secondsPassed will easily fit within + // 64-bits, and totalPriceChange will easily fit within 128-bits, their product + // will always fit within 256-bits. + int256 currentPriceChange = totalPriceChange * int256(_secondsPassed) / int256(_duration); + + // currentPriceChange can be negative, but if so, will have a magnitude + // less that _startingPrice. Thus, this result will always end up positive. + int256 currentPrice = int256(_startingPrice) + currentPriceChange; + + return uint256(currentPrice); + } + } + + /// @dev Computes owner's cut of a sale. + /// @param _price - Sale price of NFT. + function _computeCut(uint256 _price) internal view returns (uint256) { + // NOTE: We don't use SafeMath (or similar) in this function because + // all of our entry functions carefully cap the maximum values for + // currency (at 128-bits), and ownerCut <= 10000 (see the require() + // statement in the ClockAuction constructor). The result of this + // function is always guaranteed to be <= _price. + return _price * ownerCut / 10000; + } + +} + + + + + + + +/** + * @title Pausable + * @dev Base contract which allows children to implement an emergency stop mechanism. + */ +contract Pausable is Ownable { + event Pause(); + event Unpause(); + + bool public paused = false; + + + /** + * @dev modifier to allow actions only when the contract IS paused + */ + modifier whenNotPaused() { + require(!paused); + _; + } + + /** + * @dev modifier to allow actions only when the contract IS NOT paused + */ + modifier whenPaused { + require(paused); + _; + } + + /** + * @dev called by the owner to pause, triggers stopped state + */ + function pause() onlyOwner whenNotPaused public returns (bool) { + paused = true; + emit Pause(); + return true; + } + + /** + * @dev called by the owner to unpause, returns to normal state + */ + function unpause() onlyOwner whenPaused public returns (bool) { + paused = false; + emit Unpause(); + return true; + } +} + + +/// @title Clock auction for non-fungible tokens. +/// @notice We omit a fallback function to prevent accidental sends to this contract. +contract ClockAuction is Pausable, ClockAuctionBase { + + /// @dev The ERC-165 interface signature for ERC-721. + /// Ref: https://github.com/ethereum/EIPs/issues/165 + /// Ref: https://github.com/ethereum/EIPs/issues/721 + bytes4 constant InterfaceSignature_ERC721 = bytes4(0x9a20483d); + + /// @dev Constructor creates a reference to the NFT ownership contract + /// and verifies the owner cut is in the valid range. + /// @param _nftAddress - address of a deployed contract implementing + /// the Nonfungible Interface. + /// @param _cut - percent cut the owner takes on each auction, must be + /// between 0-10,000. + constructor(address _nftAddress, uint256 _cut) public { + require(_cut <= 10000); + ownerCut = _cut; + + ERC721 candidateContract = ERC721(_nftAddress); + require(candidateContract.supportsInterface(InterfaceSignature_ERC721)); + nonFungibleContract = candidateContract; + } + + /// @dev Remove all Ether from the contract, which is the owner's cuts + /// as well as any Ether sent directly to the contract address. + /// Always transfers to the NFT contract, but can be called either by + /// the owner or the NFT contract. + function withdrawBalance() external { + address payable nftAddress = address(uint160(address(nonFungibleContract))); + + require( + msg.sender == owner || + msg.sender == nftAddress + ); + // We are using this boolean method to make sure that even if one fails it will still work + bool res = nftAddress.send(address(this).balance); + } + + /// @dev Creates and begins a new auction. + /// @param _tokenId - ID of token to auction, sender must be owner. + /// @param _startingPrice - Price of item (in wei) at beginning of auction. + /// @param _endingPrice - Price of item (in wei) at end of auction. + /// @param _duration - Length of time to move between starting + /// price and ending price (in seconds). + /// @param _seller - Seller, if not the message sender + function createAuction( + uint256 _tokenId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration, + address payable _seller + ) + external + whenNotPaused + { + // Sanity check that no inputs overflow how many bits we've allocated + // to store them in the auction struct. + require(_startingPrice == uint256(uint128(_startingPrice))); + require(_endingPrice == uint256(uint128(_endingPrice))); + require(_duration == uint256(uint64(_duration))); + + require(_owns(msg.sender, _tokenId)); + _escrow(msg.sender, _tokenId); + Auction memory auction = Auction( + _seller, + uint128(_startingPrice), + uint128(_endingPrice), + uint64(_duration), + uint64(now) + ); + _addAuction(_tokenId, auction); + } + + /// @dev Bids on an open auction, completing the auction and transferring + /// ownership of the NFT if enough Ether is supplied. + /// @param _tokenId - ID of token to bid on. + function bid(uint256 _tokenId) + external + payable + whenNotPaused + { + // _bid will throw if the bid or funds transfer fails + _bid(_tokenId, msg.value); + _transfer(msg.sender, _tokenId); + } + + /// @dev Cancels an auction that hasn't been won yet. + /// Returns the NFT to original owner. + /// @notice This is a state-modifying function that can + /// be called while the contract is paused. + /// @param _tokenId - ID of token on auction + function cancelAuction(uint256 _tokenId) + external + { + Auction storage auction = tokenIdToAuction[_tokenId]; + require(_isOnAuction(auction)); + address seller = auction.seller; + require(msg.sender == seller); + _cancelAuction(_tokenId, seller); + } + + /// @dev Cancels an auction when the contract is paused. + /// Only the owner may do this, and NFTs are returned to + /// the seller. This should only be used in emergencies. + /// @param _tokenId - ID of the NFT on auction to cancel. + function cancelAuctionWhenPaused(uint256 _tokenId) + whenPaused + onlyOwner + external + { + Auction storage auction = tokenIdToAuction[_tokenId]; + require(_isOnAuction(auction)); + _cancelAuction(_tokenId, auction.seller); + } + + /// @dev Returns auction info for an NFT on auction. + /// @param _tokenId - ID of NFT on auction. + function getAuction(uint256 _tokenId) + external + view + returns + ( + address seller, + uint256 startingPrice, + uint256 endingPrice, + uint256 duration, + uint256 startedAt + ) { + Auction storage auction = tokenIdToAuction[_tokenId]; + require(_isOnAuction(auction)); + return ( + auction.seller, + auction.startingPrice, + auction.endingPrice, + auction.duration, + auction.startedAt + ); + } + + /// @dev Returns the current price of an auction. + /// @param _tokenId - ID of the token price we are checking. + function getCurrentPrice(uint256 _tokenId) + external + view + returns (uint256) + { + Auction storage auction = tokenIdToAuction[_tokenId]; + require(_isOnAuction(auction)); + return _currentPrice(auction); + } + +} + + +/// @title Reverse auction modified for siring +/// @notice We omit a fallback function to prevent accidental sends to this contract. +contract SiringClockAuction is ClockAuction { + + // @dev Sanity check that allows us to ensure that we are pointing to the + // right auction in our setSiringAuctionAddress() call. + bool public isSiringClockAuction = true; + + // Delegate constructor + constructor(address _nftAddr, uint256 _cut) public + ClockAuction(_nftAddr, _cut) {} + + /// @dev Creates and begins a new auction. Since this function is wrapped, + /// require sender to be KittyCore contract. + /// @param _tokenId - ID of token to auction, sender must be owner. + /// @param _startingPrice - Price of item (in wei) at beginning of auction. + /// @param _endingPrice - Price of item (in wei) at end of auction. + /// @param _duration - Length of auction (in seconds). + /// @param _seller - Seller, if not the message sender + function createAuction( + uint256 _tokenId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration, + address payable _seller + ) + external + { + // Sanity check that no inputs overflow how many bits we've allocated + // to store them in the auction struct. + require(_startingPrice == uint256(uint128(_startingPrice))); + require(_endingPrice == uint256(uint128(_endingPrice))); + require(_duration == uint256(uint64(_duration))); + + require(msg.sender == address(nonFungibleContract)); + _escrow(_seller, _tokenId); + Auction memory auction = Auction( + _seller, + uint128(_startingPrice), + uint128(_endingPrice), + uint64(_duration), + uint64(now) + ); + _addAuction(_tokenId, auction); + } + + /// @dev Places a bid for siring. Requires the sender + /// is the KittyCore contract because all bid methods + /// should be wrapped. Also returns the kitty to the + /// seller rather than the winner. + function bid(uint256 _tokenId) + external + payable + { + require(msg.sender == address(nonFungibleContract)); + address seller = tokenIdToAuction[_tokenId].seller; + // _bid checks that token ID is valid and will throw if bid fails + _bid(_tokenId, msg.value); + // We transfer the kitty back to the seller, the winner will get + // the offspring + _transfer(seller, _tokenId); + } + +} + + + + + +/// @title Clock auction modified for sale of kitties +/// @notice We omit a fallback function to prevent accidental sends to this contract. +contract SaleClockAuction is ClockAuction { + + // @dev Sanity check that allows us to ensure that we are pointing to the + // right auction in our setSaleAuctionAddress() call. + bool public isSaleClockAuction = true; + + // Tracks last 5 sale price of gen0 kitty sales + uint256 public gen0SaleCount; + uint256[5] public lastGen0SalePrices; + + // Delegate constructor + constructor(address _nftAddr, uint256 _cut) public + ClockAuction(_nftAddr, _cut) {} + + /// @dev Creates and begins a new auction. + /// @param _tokenId - ID of token to auction, sender must be owner. + /// @param _startingPrice - Price of item (in wei) at beginning of auction. + /// @param _endingPrice - Price of item (in wei) at end of auction. + /// @param _duration - Length of auction (in seconds). + /// @param _seller - Seller, if not the message sender + function createAuction( + uint256 _tokenId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration, + address payable _seller + ) + external + { + // Sanity check that no inputs overflow how many bits we've allocated + // to store them in the auction struct. + require(_startingPrice == uint256(uint128(_startingPrice))); + require(_endingPrice == uint256(uint128(_endingPrice))); + require(_duration == uint256(uint64(_duration))); + + require(msg.sender == address(nonFungibleContract)); + _escrow(_seller, _tokenId); + Auction memory auction = Auction( + _seller, + uint128(_startingPrice), + uint128(_endingPrice), + uint64(_duration), + uint64(now) + ); + _addAuction(_tokenId, auction); + } + + /// @dev Updates lastSalePrice if seller is the nft contract + /// Otherwise, works the same as default bid method. + function bid(uint256 _tokenId) + external + payable + { + // _bid verifies token ID size + address seller = tokenIdToAuction[_tokenId].seller; + uint256 price = _bid(_tokenId, msg.value); + _transfer(msg.sender, _tokenId); + + // If not a gen0 auction, exit + if (seller == address(nonFungibleContract)) { + // Track gen0 sale prices + lastGen0SalePrices[gen0SaleCount % 5] = price; + gen0SaleCount++; + } + } + + function averageGen0SalePrice() external view returns (uint256) { + uint256 sum = 0; + for (uint256 i = 0; i < 5; i++) { + sum += lastGen0SalePrices[i]; + } + return sum / 5; + } + +} + + + + + + + diff --git a/src/test/resources/soliditycode/contractScenario012.sol b/src/test/resources/soliditycode/contractScenario012.sol new file mode 100644 index 00000000000..7bed08dd111 --- /dev/null +++ b/src/test/resources/soliditycode/contractScenario012.sol @@ -0,0 +1,57 @@ +//pragma solidity ^0.4.0; +contract PayTest { + +uint256 public n; +constructor() payable public{ +n = 0; +} + +function nPlusOne() public{ +n = n+1; +} + +//get current contract balance +function getBalance() payable public returns (uint) { +return address(this).balance; +} + +function getSenderBalance() public view returns(address, uint) { +return (msg.sender, msg.sender.balance); +} + +address public user; + +//deposit 1 coin to msg.sender +function depositOneCoin() payable public returns(bool success){ +return msg.sender.send(1); +} + +// function transferOneCoin() payable public returns(){ +// address(msg.sender).transfer(1); +// } + +// function depositOneCoin() payable public returns(address addr, uint amount, bool success){ +// return (msg.sender, msg.value, msg.sender.send(1)); +// } + +//deposit coin to msg.sender +function deposit(uint256 money) payable public returns(bool success){ +return msg.sender.send(money); +} +// function deposit(uint money) payable public returns(address addr, uint amount, bool success){ +// return (msg.sender, msg.value, msg.sender.send(money)); +// } + +// function () payable { +// msg.sender.send(1); +// } + +function sendToAddress(address payable _receiver) payable public{ +_receiver.transfer(msg.value); +} + +function sendToAddress2(address payable _receiver) payable public{ +_receiver.transfer(5); +} + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractScenario013.sol b/src/test/resources/soliditycode/contractScenario013.sol new file mode 100644 index 00000000000..b91085d018e --- /dev/null +++ b/src/test/resources/soliditycode/contractScenario013.sol @@ -0,0 +1,8 @@ +//pragma solidity ^0.4.0; +contract timetest { + +function time() public{ +require(1 trx == 1000000 sun); + +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractScenario014.sol b/src/test/resources/soliditycode/contractScenario014.sol new file mode 100644 index 00000000000..41ea739e231 --- /dev/null +++ b/src/test/resources/soliditycode/contractScenario014.sol @@ -0,0 +1,34 @@ +//pragma solidity ^0.4.0; +contract Contract1 { + constructor() public payable{} + function send5SunToReceiver(address payable _receiver) payable public{ + _receiver.transfer(5); + } +} +contract contract2 { + address public payContract; + + constructor(address _add) payable public{ + payContract = _add; + } + + function triggerContract1(address _receiver) payable public{ + payContract.call(abi.encodeWithSignature("send5SunToReceiver(address)",_receiver)); + } + + function triggerContract1ButRevert(address _receiver) payable public{ + payContract.call(abi.encodeWithSignature("send5SunToReceiver(address)",_receiver)); + require(1 == 2); + } + +} +contract contract3 { + address public payContract; + constructor(address _add) payable public{ + payContract = _add; + } + + function triggerContract2(address _receiver) payable public{ + payContract.call(abi.encodeWithSignature("triggerContract1(address)",_receiver)); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTest.sol b/src/test/resources/soliditycode/contractTest.sol new file mode 100644 index 00000000000..409545eaabb --- /dev/null +++ b/src/test/resources/soliditycode/contractTest.sol @@ -0,0 +1,19 @@ +//pragma solidity ^0.4.4; + +contract Test{ + +function a() public returns (uint){ + +uint256 count = 0; + +for (uint256 i = 1; i > 0; i++) { + +count++; + +} + +return count; + +} + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractToMathedFeed.sol b/src/test/resources/soliditycode/contractToMathedFeed.sol new file mode 100644 index 00000000000..a5d181ad927 --- /dev/null +++ b/src/test/resources/soliditycode/contractToMathedFeed.sol @@ -0,0 +1,21 @@ +//pragma solidity ^0.4.0; + +contract ToMathedFeed { + uint public i=1; + function ToMathed (uint value) public { + i=value; + } +} + +contract ToMathedUseINContract { + function ToMathedIUseNR(address a,uint256 n) public returns(bool){ + address payContract=a; + (bool success, bytes memory data) = payContract.call(abi.encodeWithSignature("ToMathedNot(uint256)",n)); + return success; + } + function ToMathedIUseNRE(address a,uint256 value) public returns(bool){ + address payContract=a; + (bool success, bytes memory data) = payContract.call(abi.encodeWithSignature("ToMathed(uint256)",value)); + return success; + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken001.sol b/src/test/resources/soliditycode/contractTrcToken001.sol new file mode 100644 index 00000000000..0db64f36336 --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken001.sol @@ -0,0 +1,30 @@ +//pragma solidity ^0.4.24; + + contract tokenTest{ + trcToken idCon = 0; + uint256 tokenValueCon=0; + uint256 callValueCon = 0; + + // positive case + function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ + //trcToken id = 0x74657374546f6b656e; + toAddress.transferToken(amount,id); + } + + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ + trcToken id = msg.tokenid; + uint256 tokenValue = msg.tokenvalue; + uint256 callValue = msg.value; + return (id, tokenValue, callValue); + } + + constructor() public payable { + idCon = msg.tokenid; + tokenValueCon = msg.tokenvalue; + callValueCon = msg.value; + } + + function getResultInCon() public payable returns(trcToken, uint256, uint256) { + return (idCon, tokenValueCon, callValueCon); + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken002.sol b/src/test/resources/soliditycode/contractTrcToken002.sol new file mode 100644 index 00000000000..0db64f36336 --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken002.sol @@ -0,0 +1,30 @@ +//pragma solidity ^0.4.24; + + contract tokenTest{ + trcToken idCon = 0; + uint256 tokenValueCon=0; + uint256 callValueCon = 0; + + // positive case + function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ + //trcToken id = 0x74657374546f6b656e; + toAddress.transferToken(amount,id); + } + + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ + trcToken id = msg.tokenid; + uint256 tokenValue = msg.tokenvalue; + uint256 callValue = msg.value; + return (id, tokenValue, callValue); + } + + constructor() public payable { + idCon = msg.tokenid; + tokenValueCon = msg.tokenvalue; + callValueCon = msg.value; + } + + function getResultInCon() public payable returns(trcToken, uint256, uint256) { + return (idCon, tokenValueCon, callValueCon); + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken003.sol b/src/test/resources/soliditycode/contractTrcToken003.sol new file mode 100644 index 00000000000..48205199eec --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken003.sol @@ -0,0 +1,16 @@ +//pragma solidity ^0.4.24; + + contract tokenTest{ + constructor() public payable{} + // positive case + function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ + //trcToken id = 0x74657374546f6b656e; + toAddress.transferToken(amount,id); + } + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ + trcToken id = msg.tokenid; + uint256 tokenValue = msg.tokenvalue; + uint256 callValue = msg.value; + return (id, tokenValue, callValue); + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken005.sol b/src/test/resources/soliditycode/contractTrcToken005.sol new file mode 100644 index 00000000000..48205199eec --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken005.sol @@ -0,0 +1,16 @@ +//pragma solidity ^0.4.24; + + contract tokenTest{ + constructor() public payable{} + // positive case + function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ + //trcToken id = 0x74657374546f6b656e; + toAddress.transferToken(amount,id); + } + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ + trcToken id = msg.tokenid; + uint256 tokenValue = msg.tokenvalue; + uint256 callValue = msg.value; + return (id, tokenValue, callValue); + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken011.sol b/src/test/resources/soliditycode/contractTrcToken011.sol new file mode 100644 index 00000000000..f815c26b136 --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken011.sol @@ -0,0 +1,35 @@ +//pragma solidity ^0.4.24; +contract transferTokenContract { + constructor() payable public{} + function() payable external{} + function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { + toAddress.transferToken(tokenValue, id); + } + function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { + toAddress.transferToken(1, 9223372036854775809); + } + function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { + toAddress.transferToken(1, 36893488147420103233); + } + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ + trcToken id = msg.tokenid; + uint256 value = msg.tokenvalue; + return (id, value); + } + function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ + trcToken id = 1000001; + return accountAddress.tokenBalance(id); + } + function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ + return toAddress.tokenBalance(tokenId); + } +} + + +contract Result { + event log(uint256,uint256,uint256); + constructor() payable public{} + function() payable external{ + emit log(msg.tokenid,msg.tokenvalue,msg.value); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken012.sol b/src/test/resources/soliditycode/contractTrcToken012.sol new file mode 100644 index 00000000000..668f67ae205 --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken012.sol @@ -0,0 +1,26 @@ +//pragma solidity ^0.4.24; +contract transferTokenContract { + constructor() payable public{} + function() payable external{} + function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { + toAddress.transferToken(tokenValue, id); + } + function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { + toAddress.transferToken(1, 9223372036854775809); + } + function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { + toAddress.transferToken(1, 36893488147420103233); + } + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ + trcToken id = msg.tokenid; + uint256 value = msg.tokenvalue; + return (id, value); + } + function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ + trcToken id = 1000001; + return accountAddress.tokenBalance(id); + } + function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ + return toAddress.tokenBalance(tokenId); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken014.sol b/src/test/resources/soliditycode/contractTrcToken014.sol new file mode 100644 index 00000000000..3753770398a --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken014.sol @@ -0,0 +1,34 @@ +//pragma solidity ^0.4.24; +contract transferTokenContract { + constructor() payable public{} + function() payable external{} + function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { + toAddress.transferToken(tokenValue, id); + } + function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { + toAddress.transferToken(1, 9223372036854775809); + } + function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { + toAddress.transferToken(1, 36893488147420103233); + } + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ + trcToken id = msg.tokenid; + uint256 value = msg.tokenvalue; + return (id, value); + } + function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ + trcToken id = 1000001; + return accountAddress.tokenBalance(id); + } + function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ + return toAddress.tokenBalance(tokenId); + } +} + +contract Result { + event log(uint256,uint256,uint256); + constructor() payable public{} + function() payable external{ + emit log(msg.tokenid,msg.tokenvalue,msg.value); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken018.sol b/src/test/resources/soliditycode/contractTrcToken018.sol new file mode 100644 index 00000000000..668f67ae205 --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken018.sol @@ -0,0 +1,26 @@ +//pragma solidity ^0.4.24; +contract transferTokenContract { + constructor() payable public{} + function() payable external{} + function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { + toAddress.transferToken(tokenValue, id); + } + function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { + toAddress.transferToken(1, 9223372036854775809); + } + function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { + toAddress.transferToken(1, 36893488147420103233); + } + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ + trcToken id = msg.tokenid; + uint256 value = msg.tokenvalue; + return (id, value); + } + function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ + trcToken id = 1000001; + return accountAddress.tokenBalance(id); + } + function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ + return toAddress.tokenBalance(tokenId); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken023.sol b/src/test/resources/soliditycode/contractTrcToken023.sol new file mode 100644 index 00000000000..99b19beb107 --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken023.sol @@ -0,0 +1,26 @@ +//pragma solidity ^0.4.24; + + contract tokenTest{ + constructor() public payable{} + function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ + toAddress.transferToken(amount,id); + } + } + +contract B{ + uint256 public flag = 0; + constructor() public payable {} + function() external { + flag = 1; +} + +} +//pragma solidity ^0.4.24; +contract C{ + uint256 public flag = 0; + constructor() public payable {} + function() external payable { + //flag = 1; +} + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken026.sol b/src/test/resources/soliditycode/contractTrcToken026.sol new file mode 100644 index 00000000000..66635521150 --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken026.sol @@ -0,0 +1,31 @@ +//pragma solidity ^0.4.24; + +contract token{ + constructor() payable public{} + function() payable external{} + function testInCall(address callBAddress,address callCAddress, address toAddress ,uint256 amount,trcToken id) payable public{ + //callBAddress.call(bytes4(keccak256("transC(address,address,uint256,trcToken)")),callCAddress,toAddress,amount,id); + callBAddress.call(abi.encodeWithSignature("transC(address,address,uint256,trcToken)",callCAddress,toAddress,amount,id)); + } + function testIndelegateCall(address callBddress,address callAddressC, address toAddress,uint256 amount, trcToken id) payable public{ + callBddress.delegatecall(abi.encodeWithSignature("transC(address,address,uint256,trcToken)",callAddressC,toAddress,amount,id)); + } + } + + + +contract B{ + constructor() public payable{} + function() external payable{} + function transC(address payable callCAddress,address payable toAddress,uint256 amount, trcToken id) payable public{ + callCAddress.call(abi.encodeWithSignature("trans(address,uint256,trcToken)",toAddress,amount,id)); + } +} +contract C{ + constructor() payable public{} + function() payable external{} + function trans(address payable toAddress,uint256 amount, trcToken id) payable public{ + toAddress.transferToken(amount,id); + } + +} diff --git a/src/test/resources/soliditycode/contractTrcToken027.sol b/src/test/resources/soliditycode/contractTrcToken027.sol new file mode 100644 index 00000000000..ee9c1d3eb46 --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken027.sol @@ -0,0 +1,30 @@ +//pragma solidity ^0.4.24; + +contract token{ + constructor() payable public{} + function() payable external{} + function testInCall(address callBAddress,address callCAddress, address toAddress ,uint256 amount,trcToken id) payable public{ + callBAddress.call(abi.encodeWithSignature("transC(address,address,uint256,trcToken)",callCAddress,toAddress,amount,id)); + } + function testIndelegateCall(address callBddress,address callAddressC, address toAddress,uint256 amount, trcToken id) payable public{ + callBddress.delegatecall(abi.encodeWithSignature("transC(address,address,uint256,trcToken)",callAddressC,toAddress,amount,id)); + } + } + + + +contract B{ + constructor() public payable{} + function() external payable{} + function transC(address callCAddress,address toAddress,uint256 amount, trcToken id) payable public{ + callCAddress.call(abi.encodeWithSignature("trans(address,uint256,trcToken)",toAddress,amount,id)); + } +} +contract C{ + constructor() payable public{} + function() payable external{} + function trans(address payable toAddress,uint256 amount, trcToken id) payable public{ + toAddress.transferToken(amount,id); + } + +} diff --git a/src/test/resources/soliditycode/contractTrcToken028.sol b/src/test/resources/soliditycode/contractTrcToken028.sol new file mode 100644 index 00000000000..957f1c3c60d --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken028.sol @@ -0,0 +1,25 @@ +//pragma solidity ^0.4.24; + +contract token{ + uint256 public a=1; + constructor() public payable{} + function tokenBalanceWithSameName(trcToken id) public payable{ + B b= new B(); + a= b.tokenBalance(id); + } + function getA() public returns(uint256){ + return a; + } +} + + +contract B{ + uint256 public flag =0; + constructor() public payable{} + function() external payable{} + function tokenBalance(trcToken id) payable public returns(uint256){ + flag =9; + return flag; + } + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken029.sol b/src/test/resources/soliditycode/contractTrcToken029.sol new file mode 100644 index 00000000000..e8f5cbc0988 --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken029.sol @@ -0,0 +1,24 @@ +//pragma solidity ^0.4.24; + +contract token{ + address public a; + constructor() public payable{} + function transferTokenWithSameName(trcToken id,uint256 amount) public payable{ + B b= new B(); + b.transferToken(amount,id); + a= address(b); + } +} + + +contract B{ + uint256 public flag =0; + constructor() public payable{} + function() external payable{} + function transferToken(uint256 amount, trcToken id) payable public returns(bool){ + flag =9; + } + function getFlag() public view returns (uint256){ + return flag; + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken030.sol b/src/test/resources/soliditycode/contractTrcToken030.sol new file mode 100644 index 00000000000..5693292d127 --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken030.sol @@ -0,0 +1,18 @@ +//pragma solidity ^0.4.24; + + contract token{ + constructor() public payable{} + + // 4)suicide也会转移token + // 所有token,trx均被转移到toAddress, + // 若toAddress为合约地址本身,则所有token,trx均被烧掉进黑洞 + function kill(address payable toAddress) payable public{ + selfdestruct(toAddress); + } + + } + +contract B{ + constructor() public payable {} + function() external payable {} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken031.sol b/src/test/resources/soliditycode/contractTrcToken031.sol new file mode 100644 index 00000000000..5693292d127 --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken031.sol @@ -0,0 +1,18 @@ +//pragma solidity ^0.4.24; + + contract token{ + constructor() public payable{} + + // 4)suicide也会转移token + // 所有token,trx均被转移到toAddress, + // 若toAddress为合约地址本身,则所有token,trx均被烧掉进黑洞 + function kill(address payable toAddress) payable public{ + selfdestruct(toAddress); + } + + } + +contract B{ + constructor() public payable {} + function() external payable {} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken034.sol b/src/test/resources/soliditycode/contractTrcToken034.sol new file mode 100644 index 00000000000..c9a5e70a3fb --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken034.sol @@ -0,0 +1,23 @@ +//pragma solidity ^0.4.24; + + contract token{ + + // 2. 异常测试 + // 1)revert, 金额回退 + function failTransferTokenRevert(address payable toAddress,uint256 amount, trcToken id) public payable{ + toAddress.transferToken(amount,id); + require(1==2); + } + + // 2)Error, 金额回退, fee limit 扣光 + function failTransferTokenError(address payable toAddress,uint256 amount, trcToken id) public payable{ + toAddress.transferToken(amount,id); + assert(1==2); + } + + } + contract B{ + uint256 public flag = 0; + constructor() public payable {} + function() external payable {} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken035.sol b/src/test/resources/soliditycode/contractTrcToken035.sol new file mode 100644 index 00000000000..c9a5e70a3fb --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken035.sol @@ -0,0 +1,23 @@ +//pragma solidity ^0.4.24; + + contract token{ + + // 2. 异常测试 + // 1)revert, 金额回退 + function failTransferTokenRevert(address payable toAddress,uint256 amount, trcToken id) public payable{ + toAddress.transferToken(amount,id); + require(1==2); + } + + // 2)Error, 金额回退, fee limit 扣光 + function failTransferTokenError(address payable toAddress,uint256 amount, trcToken id) public payable{ + toAddress.transferToken(amount,id); + assert(1==2); + } + + } + contract B{ + uint256 public flag = 0; + constructor() public payable {} + function() external payable {} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken036.sol b/src/test/resources/soliditycode/contractTrcToken036.sol new file mode 100644 index 00000000000..6a4c61d1e07 --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken036.sol @@ -0,0 +1,52 @@ +//pragma solidity ^0.4.24; +contract IllegalDecorate { +constructor() payable public{} +function() payable external{} +event log(uint256); +function transferTokenWithPure(address payable toAddress, uint256 tokenValue) public payable { +emit log(msg.value); +emit log(msg.tokenvalue); +emit log(msg.tokenid); +toAddress.transferToken(msg.tokenvalue, msg.tokenid); +toAddress.transfer(msg.value); +} +} + +contract IllegalDecorate1 { +constructor() payable public{} +function() payable external{} +event log(uint256); +function transferTokenWithConstant(address payable toAddress, uint256 tokenValue) public payable { +emit log(msg.value); +emit log(msg.tokenvalue); +emit log(msg.tokenid); +toAddress.transferToken(msg.tokenvalue, msg.tokenid); +toAddress.transfer(msg.value); +} +} + +contract IllegalDecorate2 { +constructor() payable public{} +function() payable external{} +event log(uint256); +function transferTokenWithView(address payable toAddress, uint256 tokenValue) public payable { +emit log(msg.value); +emit log(msg.tokenvalue); +emit log(msg.tokenid); +toAddress.transferToken(msg.tokenvalue, msg.tokenid); +toAddress.transfer(msg.value); +} +} + +contract IllegalDecorate3 { +event log(uint256); +constructor() payable public{} +function() payable external{} +function transferTokenWithOutPayable(address payable toAddress, uint256 tokenValue) public { +emit log(msg.value); +emit log(msg.tokenvalue); +emit log(msg.tokenid); +toAddress.transferToken(msg.tokenvalue, msg.tokenid); +toAddress.transfer(msg.value); +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken036_1.sol b/src/test/resources/soliditycode/contractTrcToken036_1.sol new file mode 100644 index 00000000000..cd039f3e39d --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken036_1.sol @@ -0,0 +1,13 @@ +//pragma solidity ^0.4.24; +contract IllegalDecorate { +constructor() payable public{} +function() payable external{} +event log(uint256); +function transferTokenWithPure(address payable toAddress, uint256 tokenValue) public pure { +emit log(msg.value); +emit log(msg.tokenvalue); +emit log(msg.tokenid); +toAddress.transferToken(msg.tokenvalue, msg.tokenid); +toAddress.transfer(msg.value); +} +} diff --git a/src/test/resources/soliditycode/contractTrcToken036_2.sol b/src/test/resources/soliditycode/contractTrcToken036_2.sol new file mode 100644 index 00000000000..0b4d56e086b --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken036_2.sol @@ -0,0 +1,13 @@ +//pragma solidity ^0.4.24; +contract IllegalDecorate { +constructor() payable public{} +function() payable external{} +event log(uint256); +function transferTokenWithConstant(address toAddress, uint256 tokenValue) public constant { +emit log(msg.value); +emit log(msg.tokenvalue); +emit log(msg.tokenid); +toAddress.transferToken(msg.tokenvalue, msg.tokenid); +toAddress.transfer(msg.value); +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken036_3.sol b/src/test/resources/soliditycode/contractTrcToken036_3.sol new file mode 100644 index 00000000000..b8c7d750514 --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken036_3.sol @@ -0,0 +1,13 @@ +//pragma solidity ^0.4.24; +contract IllegalDecorate { +constructor() payable public{} +function() payable external{} +event log(uint256); +function transferTokenWithView(address payable toAddress, uint256 tokenValue) public view { +emit log(msg.value); +emit log(msg.tokenvalue); +emit log(msg.tokenid); +toAddress.transferToken(msg.tokenvalue, msg.tokenid); +toAddress.transfer(msg.value); +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken036_4.sol b/src/test/resources/soliditycode/contractTrcToken036_4.sol new file mode 100644 index 00000000000..29c1990962b --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken036_4.sol @@ -0,0 +1,13 @@ +//pragma solidity ^0.4.24; +contract IllegalDecorate { +event log(uint256); +constructor() payable public{} +function() payable external{} +function transferTokenWithOutPayable(address payable toAddress, uint256 tokenValue) public { +emit log(msg.value); +emit log(msg.tokenvalue); +emit log(msg.tokenid); +toAddress.transferToken(msg.tokenvalue, msg.tokenid); +toAddress.transfer(msg.value); +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken036_old.sol b/src/test/resources/soliditycode/contractTrcToken036_old.sol new file mode 100644 index 00000000000..7ea2561a1e1 --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken036_old.sol @@ -0,0 +1,41 @@ +//pragma solidity ^0.4.24; + + +contract IllegalDecorate1 { +constructor() payable public{} +function() payable public{} +event log(uint256); +function transferTokenWithConstant(address toAddress, uint256 tokenValue) public constant { +emit log(msg.value); +emit log(msg.tokenvalue); +emit log(msg.tokenid); +toAddress.transferToken(msg.tokenvalue, msg.tokenid); +toAddress.transfer(msg.value); +} +} + +contract IllegalDecorate2 { +constructor() payable public{} +function() payable public{} +event log(uint256); +function transferTokenWithView(address toAddress, uint256 tokenValue) public view { +emit log(msg.value); +emit log(msg.tokenvalue); +emit log(msg.tokenid); +toAddress.transferToken(msg.tokenvalue, msg.tokenid); +toAddress.transfer(msg.value); +} +} + +contract IllegalDecorate3 { +event log(uint256); +constructor() payable public{} +function() payable public{} +function transferTokenWithOutPayable(address toAddress, uint256 tokenValue) public { +emit log(msg.value); +emit log(msg.tokenvalue); +emit log(msg.tokenid); +toAddress.transferToken(msg.tokenvalue, msg.tokenid); +toAddress.transfer(msg.value); +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken037.sol b/src/test/resources/soliditycode/contractTrcToken037.sol new file mode 100644 index 00000000000..5e3fbcb8270 --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken037.sol @@ -0,0 +1,24 @@ +//pragma solidity ^0.4.24; + +contract transferTrc10 { + function receive(address payable rec) public payable { + uint256 aamount=address(this).tokenBalance(msg.tokenid); + uint256 bamount=rec.tokenBalance(msg.tokenid); + require(msg.tokenvalue==aamount); + require(aamount==msg.tokenvalue); + rec.transferToken(aamount,msg.tokenid); + require(0==address(this).tokenBalance(msg.tokenid)); + require(bamount+aamount==rec.tokenBalance(msg.tokenid)); + (bool success, bytes memory data) =rec.call(abi.encodeWithSignature("checkTrc10(uint256,trcToken,uint256)",bamount+aamount,msg.tokenid,0)); + require(success); + + } +} + +contract receiveTrc10 { + function() external payable {} + function checkTrc10(uint256 amount,trcToken tid,uint256 meamount) public{ + require(amount==address(this).tokenBalance(tid)); + require(meamount==msg.sender.tokenBalance(tid)); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken038.sol b/src/test/resources/soliditycode/contractTrcToken038.sol new file mode 100644 index 00000000000..713d7661e84 --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken038.sol @@ -0,0 +1,24 @@ +//pragma solidity ^0.4.24; + +contract transferTrc10 { + function receive(address payable rec) public payable { + uint256 aamount=address(this).tokenBalance(msg.tokenid); + uint256 bamount=rec.tokenBalance(msg.tokenid); + require(msg.tokenvalue==aamount); + require(aamount==msg.tokenvalue); + rec.transferToken(aamount,msg.tokenid); + //require(rec.call(abi.encode(bytes4(keccak256("AssertError()"))))); + (bool suc, bytes memory data) = rec.call(abi.encodeWithSignature("AssertError()")); + require(suc); + require(aamount==address(this).tokenBalance(msg.tokenid)); + require(bamount==rec.tokenBalance(msg.tokenid)); + } +} + +contract receiveTrc10 { + function() external payable { + } + function AssertError() public{ + assert(1==2); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken039.sol b/src/test/resources/soliditycode/contractTrcToken039.sol new file mode 100644 index 00000000000..e60b3285652 --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken039.sol @@ -0,0 +1,44 @@ +//pragma solidity ^0.4.24; +/* + * 1. caller账户issue一个token + * 2. caller部署proxy, 传入1000 token,1000 trx + * 3. caller部署A + * 4. caller部署B + * 5. caller调用proxy中upgradetTo函数,传入A的地址 + * 6. caller调用proxy中不存在的trans(uint256,address,trcToken)函数,注意这时trcToken是无意义的,但也带上tokenid。address是任意另外某账户的地址 + * 7. 可以看到目标地址trx增长5,caller账户trx减少5 + * 8. caller调用proxy中upgradeTo函数,传入B的地址 + * 9. caller调用proxy中不存在的trans(uint256,address,trcToken)函数。 + * 10. 可以看到目标地址token增长5,caller账户token减少5 +*/ +contract Proxy { + constructor() payable public{} + address public implementation; + function upgradeTo(address _address) public { + implementation = _address; + } + function() payable external{ + address addr = implementation; + require(addr != address(0)); + assembly { + let freememstart := mload(0x40) + calldatacopy(freememstart, 0, calldatasize()) + let success := delegatecall(not(0), addr, freememstart, calldatasize(), freememstart, 0) + returndatacopy(freememstart, 0, returndatasize()) + switch success + case 0 { revert(freememstart, returndatasize()) } + default { return(freememstart, returndatasize()) } + } + } +} + +contract A { + function trans(uint256 amount, address payable toAddress, trcToken id) payable public { + toAddress.transfer(amount); + } +} +contract B{ + function trans(uint256 amount, address payable toAddress, trcToken id) payable public { + toAddress.transferToken(amount,id); + } +} diff --git a/src/test/resources/soliditycode/contractTrcToken041.sol b/src/test/resources/soliditycode/contractTrcToken041.sol new file mode 100644 index 00000000000..a6272bc813d --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken041.sol @@ -0,0 +1,20 @@ +//pragma solidity ^0.4.24; + + contract tokenTest{ + constructor() public payable{} + // positive case + function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ + //trcToken id = 0x74657374546f6b656e; + toAddress.transferToken(amount,id); + } + } + +contract B{ + uint256 public flag = 0; + constructor() public payable {} + function() external payable {} + + function setFlag() public payable{ + flag = 1; + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken043.sol b/src/test/resources/soliditycode/contractTrcToken043.sol new file mode 100644 index 00000000000..f815c26b136 --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken043.sol @@ -0,0 +1,35 @@ +//pragma solidity ^0.4.24; +contract transferTokenContract { + constructor() payable public{} + function() payable external{} + function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { + toAddress.transferToken(tokenValue, id); + } + function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { + toAddress.transferToken(1, 9223372036854775809); + } + function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { + toAddress.transferToken(1, 36893488147420103233); + } + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ + trcToken id = msg.tokenid; + uint256 value = msg.tokenvalue; + return (id, value); + } + function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ + trcToken id = 1000001; + return accountAddress.tokenBalance(id); + } + function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ + return toAddress.tokenBalance(tokenId); + } +} + + +contract Result { + event log(uint256,uint256,uint256); + constructor() payable public{} + function() payable external{ + emit log(msg.tokenid,msg.tokenvalue,msg.value); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken048.sol b/src/test/resources/soliditycode/contractTrcToken048.sol new file mode 100644 index 00000000000..de2844608c0 --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken048.sol @@ -0,0 +1,14 @@ +//pragma solidity ^0.4.24; + + contract Test { + event log(uint256); + function testMsgTokenValue() payable public returns(uint256 value) { + emit log(msg.tokenvalue); + return msg.tokenvalue; + } + + function testMsgValue() payable public returns(uint256 value) { + emit log(msg.value); + return msg.value; + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken049.sol b/src/test/resources/soliditycode/contractTrcToken049.sol new file mode 100644 index 00000000000..3fd502c89fd --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken049.sol @@ -0,0 +1,10 @@ +//pragma solidity ^0.4.24; + + contract tokenTest{ + constructor() public payable{} + // positive case + function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ + //trcToken id = 0x74657374546f6b656e; + toAddress.transferToken(amount,id); + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken050.sol b/src/test/resources/soliditycode/contractTrcToken050.sol new file mode 100644 index 00000000000..3fd502c89fd --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken050.sol @@ -0,0 +1,10 @@ +//pragma solidity ^0.4.24; + + contract tokenTest{ + constructor() public payable{} + // positive case + function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ + //trcToken id = 0x74657374546f6b656e; + toAddress.transferToken(amount,id); + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken051.sol b/src/test/resources/soliditycode/contractTrcToken051.sol new file mode 100644 index 00000000000..b5b9efd4817 --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken051.sol @@ -0,0 +1,11 @@ +//pragma solidity ^0.4.24; + + contract tokenTest{ + constructor() public payable{} + function() external payable{} + // positive case + function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ + //trcToken id = 0x74657374546f6b656e; + toAddress.transferToken(amount,id); + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken052.sol b/src/test/resources/soliditycode/contractTrcToken052.sol new file mode 100644 index 00000000000..3fd502c89fd --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken052.sol @@ -0,0 +1,10 @@ +//pragma solidity ^0.4.24; + + contract tokenTest{ + constructor() public payable{} + // positive case + function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ + //trcToken id = 0x74657374546f6b656e; + toAddress.transferToken(amount,id); + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken054.sol b/src/test/resources/soliditycode/contractTrcToken054.sol new file mode 100644 index 00000000000..48205199eec --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken054.sol @@ -0,0 +1,16 @@ +//pragma solidity ^0.4.24; + + contract tokenTest{ + constructor() public payable{} + // positive case + function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ + //trcToken id = 0x74657374546f6b656e; + toAddress.transferToken(amount,id); + } + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ + trcToken id = msg.tokenid; + uint256 tokenValue = msg.tokenvalue; + uint256 callValue = msg.value; + return (id, tokenValue, callValue); + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken055.sol b/src/test/resources/soliditycode/contractTrcToken055.sol new file mode 100644 index 00000000000..48205199eec --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken055.sol @@ -0,0 +1,16 @@ +//pragma solidity ^0.4.24; + + contract tokenTest{ + constructor() public payable{} + // positive case + function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ + //trcToken id = 0x74657374546f6b656e; + toAddress.transferToken(amount,id); + } + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ + trcToken id = msg.tokenid; + uint256 tokenValue = msg.tokenvalue; + uint256 callValue = msg.value; + return (id, tokenValue, callValue); + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken060.sol b/src/test/resources/soliditycode/contractTrcToken060.sol new file mode 100644 index 00000000000..0db64f36336 --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken060.sol @@ -0,0 +1,30 @@ +//pragma solidity ^0.4.24; + + contract tokenTest{ + trcToken idCon = 0; + uint256 tokenValueCon=0; + uint256 callValueCon = 0; + + // positive case + function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ + //trcToken id = 0x74657374546f6b656e; + toAddress.transferToken(amount,id); + } + + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ + trcToken id = msg.tokenid; + uint256 tokenValue = msg.tokenvalue; + uint256 callValue = msg.value; + return (id, tokenValue, callValue); + } + + constructor() public payable { + idCon = msg.tokenid; + tokenValueCon = msg.tokenvalue; + callValueCon = msg.value; + } + + function getResultInCon() public payable returns(trcToken, uint256, uint256) { + return (idCon, tokenValueCon, callValueCon); + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken061.sol b/src/test/resources/soliditycode/contractTrcToken061.sol new file mode 100644 index 00000000000..0db64f36336 --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken061.sol @@ -0,0 +1,30 @@ +//pragma solidity ^0.4.24; + + contract tokenTest{ + trcToken idCon = 0; + uint256 tokenValueCon=0; + uint256 callValueCon = 0; + + // positive case + function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ + //trcToken id = 0x74657374546f6b656e; + toAddress.transferToken(amount,id); + } + + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ + trcToken id = msg.tokenid; + uint256 tokenValue = msg.tokenvalue; + uint256 callValue = msg.value; + return (id, tokenValue, callValue); + } + + constructor() public payable { + idCon = msg.tokenid; + tokenValueCon = msg.tokenvalue; + callValueCon = msg.value; + } + + function getResultInCon() public payable returns(trcToken, uint256, uint256) { + return (idCon, tokenValueCon, callValueCon); + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken064.sol b/src/test/resources/soliditycode/contractTrcToken064.sol new file mode 100644 index 00000000000..cf2a6fe8097 --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken064.sol @@ -0,0 +1,49 @@ +//pragma solidity ^0.4.24; +contract transferTokenContract { + constructor() payable public{} + function() payable external{} + function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { + toAddress.transferToken(tokenValue, id); + } + function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { + toAddress.transferToken(1, 9223372036854775809); + } + function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { + toAddress.transferToken(1, 36893488147420103233); + } + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ + trcToken id = msg.tokenid; + uint256 value = msg.tokenvalue; + return (id, value); + } + function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ + trcToken id = 1000001; + return accountAddress.tokenBalance(id); + } + function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ + return toAddress.tokenBalance(tokenId); + } + function transferTokenTestValueMaxBigInteger(address payable toAddress) payable public { + toAddress.transferToken(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, 0); + } + function transferTokenTestValueOverBigInteger(address payable toAddress) payable public { + toAddress.transferToken(9223372036854775808, 1000001); + } + function transferTokenTestValueMaxLong(address payable toAddress) payable public { + toAddress.transferToken(9223372036854775807, 1000001); + } + function transferTokenTestValue0IdBigInteger(address payable toAddress) payable public { + toAddress.transferToken(0, 9223372036854775809); + } +} + + + + +contract Result { + event log(uint256,uint256,uint256); + constructor() payable public{} + function() payable external{ + emit log(msg.tokenid,msg.tokenvalue,msg.value); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken066.sol b/src/test/resources/soliditycode/contractTrcToken066.sol new file mode 100644 index 00000000000..f815c26b136 --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken066.sol @@ -0,0 +1,35 @@ +//pragma solidity ^0.4.24; +contract transferTokenContract { + constructor() payable public{} + function() payable external{} + function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { + toAddress.transferToken(tokenValue, id); + } + function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { + toAddress.transferToken(1, 9223372036854775809); + } + function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { + toAddress.transferToken(1, 36893488147420103233); + } + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ + trcToken id = msg.tokenid; + uint256 value = msg.tokenvalue; + return (id, value); + } + function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ + trcToken id = 1000001; + return accountAddress.tokenBalance(id); + } + function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ + return toAddress.tokenBalance(tokenId); + } +} + + +contract Result { + event log(uint256,uint256,uint256); + constructor() payable public{} + function() payable external{ + emit log(msg.tokenid,msg.tokenvalue,msg.value); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken067.sol b/src/test/resources/soliditycode/contractTrcToken067.sol new file mode 100644 index 00000000000..f815c26b136 --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken067.sol @@ -0,0 +1,35 @@ +//pragma solidity ^0.4.24; +contract transferTokenContract { + constructor() payable public{} + function() payable external{} + function transferTokenTest(address payable toAddress, uint256 tokenValue, trcToken id) payable public { + toAddress.transferToken(tokenValue, id); + } + function transferTokenTestIDOverBigInteger(address payable toAddress) payable public { + toAddress.transferToken(1, 9223372036854775809); + } + function transferTokenTestValueRandomIdBigInteger(address payable toAddress) payable public { + toAddress.transferToken(1, 36893488147420103233); + } + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ + trcToken id = msg.tokenid; + uint256 value = msg.tokenvalue; + return (id, value); + } + function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ + trcToken id = 1000001; + return accountAddress.tokenBalance(id); + } + function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ + return toAddress.tokenBalance(tokenId); + } +} + + +contract Result { + event log(uint256,uint256,uint256); + constructor() payable public{} + function() payable external{ + emit log(msg.tokenid,msg.tokenvalue,msg.value); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken073.sol b/src/test/resources/soliditycode/contractTrcToken073.sol new file mode 100644 index 00000000000..9cb13ec7268 --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken073.sol @@ -0,0 +1,17 @@ +//pragma solidity ^0.4.0; + +contract Dest { + event logFallback(uint256 indexed, uint256 indexed, uint256 indexed); + event logGetToken(uint256 indexed, uint256 indexed, uint256 indexed, uint256); + + + constructor() payable public {} + + function getToken(trcToken tokenId) payable public{ + emit logGetToken(msg.sender.tokenBalance(tokenId), msg.tokenid, msg.tokenvalue, msg.value); + } + + function () payable external{ + emit logFallback(msg.tokenid, msg.tokenvalue, msg.value); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken075.sol b/src/test/resources/soliditycode/contractTrcToken075.sol new file mode 100644 index 00000000000..2a32fd7e8d3 --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken075.sol @@ -0,0 +1,26 @@ +//pragma solidity ^0.4.0; + +contract Dest { + event logFallback(uint256 indexed, uint256 indexed, uint256 indexed); + event logGetToken(uint256 indexed, uint256 indexed, uint256 indexed, uint256); + + constructor() payable public {} + + function getToken(trcToken tokenId) payable public{ + emit logGetToken(msg.sender.tokenBalance(tokenId), msg.tokenid, msg.tokenvalue, msg.value); + } + + function getTokenLongMin() payable public{ + // long.min - 1000020 + emit logGetToken(msg.sender.tokenBalance(trcToken(-9223372036855775828)), msg.tokenid, msg.tokenvalue, msg.value); + } + + function getTokenLongMax() payable public{ + // long.max + 1000020 + emit logGetToken(msg.sender.tokenBalance(trcToken(9223372036855775827)), msg.tokenid, msg.tokenvalue, msg.value); + } + + function () payable external{ + emit logFallback(msg.tokenid, msg.tokenvalue, msg.value); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken076.sol b/src/test/resources/soliditycode/contractTrcToken076.sol new file mode 100644 index 00000000000..9de79a327c3 --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken076.sol @@ -0,0 +1,19 @@ +//pragma solidity ^0.4.24; +contract Test { + address public origin; + address public sender; + bool public result1; + bool public result2; + function test() external { + origin = tx.origin; + sender = msg.sender; + result1 = msg.sender == tx.origin; // true + result2 = origin == sender; // true + } +function getResult1() public returns(bool){ + return result1; +} +function getResult2() public returns(bool){ + return result2; +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken077.sol b/src/test/resources/soliditycode/contractTrcToken077.sol new file mode 100644 index 00000000000..e110f24e2fc --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken077.sol @@ -0,0 +1,11 @@ +//pragma solidity ^0.4.24; + +contract trcToken077 { +function addressTest() public returns(bytes32 addressValue) { + assembly{ + let x := mload(0x40) //Find empty storage location using "free memory pointer" + mstore(x,address) //Place current contract address + addressValue := mload(x) + } + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken078.sol b/src/test/resources/soliditycode/contractTrcToken078.sol new file mode 100644 index 00000000000..f7504ea55aa --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken078.sol @@ -0,0 +1,35 @@ +//pragma solidity ^0.4.24; +contract callerContract { + constructor() public payable{} + function() external payable{} + function sendToB(address called_address, address c) public payable{ + called_address.delegatecall(abi.encodeWithSignature("transferTo(address)",c)); + } + function sendToB2(address called_address,address c) public payable{ + called_address.call(abi.encodeWithSignature("transferTo(address)",c)); + } + function sendToB3(address called_address,address c) public payable{ + called_address.delegatecall(abi.encodeWithSignature("transferTo(address)",c)); + } +} + contract calledContract { + function() external payable{} + constructor() public payable {} + function transferTo(address payable toAddress)public payable{ + toAddress.transfer(5); + } + + function setIinC(address c) public payable{ + c.call.value(5)(abi.encode(bytes4(keccak256("setI()")))); + } + + } + contract c{ + address public origin; + address public sender; + constructor() public payable{} + event log(address,address); + function() payable external{ + emit log(tx.origin,msg.sender); + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken079.sol b/src/test/resources/soliditycode/contractTrcToken079.sol new file mode 100644 index 00000000000..48205199eec --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken079.sol @@ -0,0 +1,16 @@ +//pragma solidity ^0.4.24; + + contract tokenTest{ + constructor() public payable{} + // positive case + function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ + //trcToken id = 0x74657374546f6b656e; + toAddress.transferToken(amount,id); + } + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ + trcToken id = msg.tokenid; + uint256 tokenValue = msg.tokenvalue; + uint256 callValue = msg.value; + return (id, tokenValue, callValue); + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcToken080.sol b/src/test/resources/soliditycode/contractTrcToken080.sol new file mode 100644 index 00000000000..27529ce48e8 --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcToken080.sol @@ -0,0 +1,30 @@ +//pragma solidity ^0.4.24; + + contract tokenTest{ + trcToken idCon = 0; + uint256 tokenValueCon=0; + uint256 callValueCon = 0; + function() external payable{} + // positive case + function TransferTokenTo(address payable toAddress, trcToken id,uint256 amount) public payable{ + //trcToken id = 0x74657374546f6b656e; + toAddress.transferToken(amount,id); + } + + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ + trcToken id = msg.tokenid; + uint256 tokenValue = msg.tokenvalue; + uint256 callValue = msg.value; + return (id, tokenValue, callValue); + } + + constructor() public payable { + idCon = msg.tokenid; + tokenValueCon = msg.tokenvalue; + callValueCon = msg.value; + } + + function getResultInCon() public payable returns(trcToken, uint256, uint256) { + return (idCon, tokenValueCon, callValueCon); + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractTrcTokenToOther.sol b/src/test/resources/soliditycode/contractTrcTokenToOther.sol new file mode 100644 index 00000000000..22456df9e8e --- /dev/null +++ b/src/test/resources/soliditycode/contractTrcTokenToOther.sol @@ -0,0 +1,44 @@ +//pragma solidity ^0.4.24; + +contract ConvertType { + +constructor() payable public{} + +function() payable external{} + +//function trcTokenOnStorage(trcToken storage token) internal { // ERROR: Data location can only be specified for array, struct or mapping types, but "storage" was given. +//} + +function trcTokenToString(trcToken token) public pure returns(string memory s){ +// s = token; // ERROR +// s = string(token); // ERROR +} + +function trcTokenToUint256(trcToken token) public pure returns(uint256 r){ +uint256 u = token; // OK +uint256 u2 = uint256(token); // OK +r = u2; +} + +function trcTokenToAddress(trcToken token) public pure returns(address r){ +//r = token; // ERROR +token = 0x1234567812345678123456781234567812345678123456781234567812345678; +address a2 = address(token); // OK +r = a2; +} + +function trcTokenToBytes(trcToken token) public pure returns(bytes memory r){ +//r = token; // ERROR +// r = bytes(token); // ERROR +} + +function trcTokenToBytes32(trcToken token) public pure returns(bytes32 r){ +// r = token; // ERROR +bytes32 b2 = bytes32(token); // OK +r = b2; +} + +function trcTokenToArray(trcToken token) public pure returns(uint[] memory r){ +//r = token; // ERROR +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/contractUnknownException.sol b/src/test/resources/soliditycode/contractUnknownException.sol new file mode 100644 index 00000000000..37c28468be1 --- /dev/null +++ b/src/test/resources/soliditycode/contractUnknownException.sol @@ -0,0 +1,65 @@ +// pragma solidity ^0.4.24; + +contract testA { + constructor() public payable { + A a = (new A).value(10)(); + a.fun(); + } +} + +contract testB { + constructor() public payable { + B b = (new B).value(10)(); + b.fun(); + } +} + + +contract testC { + constructor() public payable{ + C c = (new C).value(10)(); + c.fun(); + } +} + +contract testD { + constructor() public payable{ + D d = (new D).value(10)(); + d.fun(); + } +} + + +contract A { + constructor() public payable{ + selfdestruct(msg.sender); + } + function fun() public { + } + +} + +contract B { + constructor() public payable { + revert(); + } + function fun() public { + } +} + + +contract C { + constructor() public payable { + assert(1==2); + } + function fun() public { + } +} + +contract D { + constructor() public payable { + require(1==2); + } + function fun() public { + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/requireExceptiontest1TestRequireContract.sol b/src/test/resources/soliditycode/requireExceptiontest1TestRequireContract.sol new file mode 100644 index 00000000000..dbb97ab4f04 --- /dev/null +++ b/src/test/resources/soliditycode/requireExceptiontest1TestRequireContract.sol @@ -0,0 +1,15 @@ +//pragma solidity ^0.4.0; +contract TestThrowsContract{ + function testAssert() public { + assert(1==2); + } + function testRequire() public { + require(2==1); + } + function testRevert() public { + revert(); + } + //function testThrow(){ + // throw; + //} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/requireExceptiontest2TestThrowsContract.sol b/src/test/resources/soliditycode/requireExceptiontest2TestThrowsContract.sol new file mode 100644 index 00000000000..abcc2d84ca2 --- /dev/null +++ b/src/test/resources/soliditycode/requireExceptiontest2TestThrowsContract.sol @@ -0,0 +1,15 @@ +//pragma solidity ^0.4.0; +contract TestThrowsContract{ + function testAssert() public { + assert(1==2); + } + function testRequire() public { + require(2==1); + } + function testRevert() public { + revert(); + } + // function testThrow() public { + // throw; + //} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/requireExceptiontest3TestRevertContract.sol b/src/test/resources/soliditycode/requireExceptiontest3TestRevertContract.sol new file mode 100644 index 00000000000..229fa6a74b0 --- /dev/null +++ b/src/test/resources/soliditycode/requireExceptiontest3TestRevertContract.sol @@ -0,0 +1,15 @@ +//pragma solidity ^0.4.0; +contract TestThrowsContract{ + function testAssert() public { + assert(1==2); + } + function testRequire() public { + require(2==1); + } + function testRevert() public { + revert(); + } + // function testThrow(){ + // throw; + // } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/requireExceptiontest4noPayableContract.sol b/src/test/resources/soliditycode/requireExceptiontest4noPayableContract.sol new file mode 100644 index 00000000000..aa043ad9c3b --- /dev/null +++ b/src/test/resources/soliditycode/requireExceptiontest4noPayableContract.sol @@ -0,0 +1,8 @@ +//pragma solidity ^0.4.0; + +contract noPayableContract { + +function noPayable() public payable returns (uint){ +return msg.value; +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/requireExceptiontest4noPayableContract_1.sol b/src/test/resources/soliditycode/requireExceptiontest4noPayableContract_1.sol new file mode 100644 index 00000000000..fe7ba275736 --- /dev/null +++ b/src/test/resources/soliditycode/requireExceptiontest4noPayableContract_1.sol @@ -0,0 +1,8 @@ +//pragma solidity ^0.4.0; + +contract noPayableContract { + +function noPayable() public returns (uint){ +return msg.value; +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/requireExceptiontest5noPayableConstructor.sol b/src/test/resources/soliditycode/requireExceptiontest5noPayableConstructor.sol new file mode 100644 index 00000000000..e1733b0562b --- /dev/null +++ b/src/test/resources/soliditycode/requireExceptiontest5noPayableConstructor.sol @@ -0,0 +1,11 @@ +//pragma solidity ^0.4.0; + +contract MyContract { + uint money; + + //function MyContract(uint _money) { + constructor(uint _money) public payable{ + require(msg.value >= _money); + money = _money; + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/requireExceptiontest5noPayableConstructor_1.sol b/src/test/resources/soliditycode/requireExceptiontest5noPayableConstructor_1.sol new file mode 100644 index 00000000000..793b468d4c2 --- /dev/null +++ b/src/test/resources/soliditycode/requireExceptiontest5noPayableConstructor_1.sol @@ -0,0 +1,11 @@ +//pragma solidity ^0.4.0; + +contract MyContract { + uint money; + + //function MyContract(uint _money) { + constructor(uint _money) public { + require(msg.value >= _money); + money = _money; + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/requireExceptiontest6transferTestContract.sol b/src/test/resources/soliditycode/requireExceptiontest6transferTestContract.sol new file mode 100644 index 00000000000..8c64ff740cd --- /dev/null +++ b/src/test/resources/soliditycode/requireExceptiontest6transferTestContract.sol @@ -0,0 +1,8 @@ +//pragma solidity ^0.4.0; + +contract transferTestContract { + function tranferTest(address payable addr) public payable{ + addr.transfer(10); + + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/requireExceptiontest7payableFallbakContract.sol b/src/test/resources/soliditycode/requireExceptiontest7payableFallbakContract.sol new file mode 100644 index 00000000000..85cf454e08e --- /dev/null +++ b/src/test/resources/soliditycode/requireExceptiontest7payableFallbakContract.sol @@ -0,0 +1,14 @@ +//pragma solidity ^0.4.0; + +contract Test { + function() external { x = 1; } + uint x; +} + + +contract Caller { + function callTest(Test test) public { + //test.call(0xabcdef01); // hash does not exist + address(test).call(abi.encode(0xabcdef01)); // hash does not exist + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/requireExceptiontest8newContractGasNoenough.sol b/src/test/resources/soliditycode/requireExceptiontest8newContractGasNoenough.sol new file mode 100644 index 00000000000..b322ac68591 --- /dev/null +++ b/src/test/resources/soliditycode/requireExceptiontest8newContractGasNoenough.sol @@ -0,0 +1,19 @@ +//pragma solidity ^0.4.0; + +contract Account{ + uint256 public accId; + + // function Account(uint accountId) payable{ + constructor(uint accountId) payable public { + accId = accountId; + } +} + +contract Initialize{ + // Account public account = new Account(10); + + function newAccount() public { + Account account = new Account(1); + } + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/requireExceptiontest9MessageUsedErrorFeed.sol b/src/test/resources/soliditycode/requireExceptiontest9MessageUsedErrorFeed.sol new file mode 100644 index 00000000000..05448bfd0ac --- /dev/null +++ b/src/test/resources/soliditycode/requireExceptiontest9MessageUsedErrorFeed.sol @@ -0,0 +1,18 @@ +//pragma solidity ^0.4.0; + +contract MathedFeed { + + function divideMathed() public returns (uint ret) { + uint x=1; + uint y=0; + return x/y; + } +} + + +contract MathedUseContract { + + function MathedUse(address addr) public returns (uint) { + return MathedFeed(addr).divideMathed(); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/requireExceptiontestFunctionUsedErrorFeed.sol b/src/test/resources/soliditycode/requireExceptiontestFunctionUsedErrorFeed.sol new file mode 100644 index 00000000000..b7f5244954d --- /dev/null +++ b/src/test/resources/soliditycode/requireExceptiontestFunctionUsedErrorFeed.sol @@ -0,0 +1,17 @@ +//pragma solidity ^0.4.0; + +contract MessageFeed { + + function mValue() payable public returns (uint ret) { + return msg.value; + } +} + +contract MessageUseContract { + function inputValue() payable public returns (uint){ + return msg.value; + } + function messageUse(address addr) payable public returns (uint) { + return MessageFeed(addr).mValue.value(1)(); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode/walletTestMutiSign004.sol b/src/test/resources/soliditycode/walletTestMutiSign004.sol new file mode 100644 index 00000000000..7b943aee5c1 --- /dev/null +++ b/src/test/resources/soliditycode/walletTestMutiSign004.sol @@ -0,0 +1,51 @@ +contract timeoutTest { + string public iarray1; + // cpu + function oneCpu() public { + require(1==1); + } + + function storage8Char() public { + iarray1 = "12345678"; + } + + function testUseCpu(uint256 a) public returns (uint256){ + uint256 count = 0; + for (uint256 i = 0; i < a; i++) { + count++; + } + return count; + } + + + uint256[] public iarray; + uint public calculatedFibNumber; + mapping(address=>mapping(address=>uint256)) public m; + + function testUseStorage(uint256 a) public returns (uint256){ + uint256 count = 0; + for (uint256 i = 0; i < a; i++) { + count++; + iarray.push(i); + } + return count; + } + + // stack + //uint n = 0; + uint yy = 0; + function test() public { + //n += 1; + yy += 1; + test(); + } + + function setFibonacci(uint n) public returns (uint256){ + calculatedFibNumber = fibonacci(n); + return calculatedFibNumber; + } + + function fibonacci(uint n) internal returns (uint) { + return fibonacci(n - 1) + fibonacci(n - 2); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/addMsg001Nonpayable.sol b/src/test/resources/soliditycode_v0.4.25/addMsg001Nonpayable.sol new file mode 100644 index 00000000000..7b124f0e870 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/addMsg001Nonpayable.sol @@ -0,0 +1,20 @@ +//pragma solidity ^0.4.24; + +contract IllegalDecorate { + +event log(uint256); +constructor() payable public{} + +function() payable public{} + +function transferTokenWithOutPayable(address toAddress, uint256 tokenValue) public { +// function transferTokenWithValue(address toAddress, uint256 tokenValue) payable public { +emit log(msg.value); +emit log(msg.tokenvalue); +emit log(msg.tokenid); +toAddress.transferToken(msg.tokenvalue, msg.tokenid); +toAddress.transfer(msg.value); + +} + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/addMsg002View.sol b/src/test/resources/soliditycode_v0.4.25/addMsg002View.sol new file mode 100644 index 00000000000..97c07ace501 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/addMsg002View.sol @@ -0,0 +1,20 @@ +//pragma solidity ^0.4.24; + +contract IllegalDecorate { + +constructor() payable public{} + +function() payable public{} + +event log(uint256); + +function transferTokenWithView(address toAddress, uint256 tokenValue) public view { +emit log(msg.value); +emit log(msg.tokenvalue); +emit log(msg.tokenid); +toAddress.transferToken(msg.tokenvalue, msg.tokenid); +toAddress.transfer(msg.value); +} + +} + diff --git a/src/test/resources/soliditycode_v0.4.25/addMsg003Constant.sol b/src/test/resources/soliditycode_v0.4.25/addMsg003Constant.sol new file mode 100644 index 00000000000..4cc69e05c90 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/addMsg003Constant.sol @@ -0,0 +1,19 @@ +//pragma solidity ^0.4.24; + +contract IllegalDecorate { + +constructor() payable public{} + +function() payable public{} + +event log(uint256); + +function transferTokenWithConstant(address toAddress, uint256 tokenValue) public constant { +emit log(msg.value); +emit log(msg.tokenvalue); +emit log(msg.tokenid); +toAddress.transferToken(msg.tokenvalue, msg.tokenid); +toAddress.transfer(msg.value); +} + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/addMsg004Pure.sol b/src/test/resources/soliditycode_v0.4.25/addMsg004Pure.sol new file mode 100644 index 00000000000..886e5d2ea0f --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/addMsg004Pure.sol @@ -0,0 +1,19 @@ +//pragma solidity ^0.4.24; + +contract IllegalDecorate { + +constructor() payable public{} + +function() payable public{} + +event log(uint256); + +function transferTokenWithPure(address toAddress, uint256 tokenValue) public pure { +emit log(msg.value); +emit log(msg.tokenvalue); +emit log(msg.tokenid); +toAddress.transferToken(msg.tokenvalue, msg.tokenid); +toAddress.transfer(msg.value); +} + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/addTransferToken001Nonpayable.sol b/src/test/resources/soliditycode_v0.4.25/addTransferToken001Nonpayable.sol new file mode 100644 index 00000000000..b6c69fca887 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/addTransferToken001Nonpayable.sol @@ -0,0 +1,15 @@ +//pragma solidity ^0.4.24; + + contract IllegalDecorate { + + constructor() payable public{} + + function() payable public{} + + function transferTokenWithOutPayable(address toAddress, uint256 tokenValue)public { + + toAddress.transferToken(tokenValue, 0x6e6d62); + + } + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/addTransferToken002View.sol b/src/test/resources/soliditycode_v0.4.25/addTransferToken002View.sol new file mode 100644 index 00000000000..fc390f12b53 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/addTransferToken002View.sol @@ -0,0 +1,15 @@ +//pragma solidity ^0.4.24; + +contract IllegalDecorate { + + constructor() payable public{} + + function() payable public{} + + function transferTokenWithView(address toAddress, uint256 tokenValue) public view { + + toAddress.transferToken(tokenValue, 0x6e6d62); + + } + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/addTransferToken003Constant.sol b/src/test/resources/soliditycode_v0.4.25/addTransferToken003Constant.sol new file mode 100644 index 00000000000..38c034f6bfb --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/addTransferToken003Constant.sol @@ -0,0 +1,15 @@ +//pragma solidity ^0.4.24; + +contract IllegalDecorate { + + constructor() payable public{} + + function() payable public{} + + function transferTokenWithConstant(address toAddress, uint256 tokenValue)public constant { + + toAddress.transferToken(tokenValue, 0x6e6d62); + + } + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/addTransferToken004Pure.sol b/src/test/resources/soliditycode_v0.4.25/addTransferToken004Pure.sol new file mode 100644 index 00000000000..085fd1bbbdb --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/addTransferToken004Pure.sol @@ -0,0 +1,15 @@ +//pragma solidity ^0.4.24; + +contract IllegalDecorate { + + constructor() payable public{} + + function() payable public{} + + function transferTokenWithPure(address toAddress, uint256 tokenValue) public pure { + + toAddress.transferToken(tokenValue, 0x6e6d62); + + } + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/addTrcToken001Assemble.sol b/src/test/resources/soliditycode_v0.4.25/addTrcToken001Assemble.sol new file mode 100644 index 00000000000..a0015c9e75b --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/addTrcToken001Assemble.sol @@ -0,0 +1,81 @@ +//pragma solidity ^0.4.24; + +contract InAssemble { + +mapping(trcToken => uint256) tokenCnt; +mapping(uint256 => mapping(trcToken => trcToken)) cntTokenToken; +constructor () payable {} +function getBalance(address addr) constant returns(uint256 r) { +assembly{ +r := balance(addr) +} +} + +function getTokenBalanceConstant(address addr, trcToken tokenId) constant returns(uint256 r) { +assembly{ +r := tokenbalance(tokenId, addr) +} +} + +function getTokenBalance(address addr, trcToken tokenId) returns(uint256 r) { +assembly{ +r := tokenbalance(tokenId, addr) +} +} + +function transferTokenInAssembly(address addr, trcToken tokenId, uint256 tokenValue) payable { +bytes4 sig = bytes4(keccak256("()")); // function signature + +assembly { +let x := mload(0x40) // get empty storage location +mstore(x,sig) // 4 bytes - place signature in empty storage + +let ret := calltoken(gas, addr, tokenValue, tokenId, +x, // input +0x04, // input size = 4 bytes +x, // output stored at input location, save space +0x0 // output size = 0 bytes +) + +// let ret := calltoken(gas, addr, tokenValue, +// x, // input +// 0x04, // input size = 4 bytes +// x, // output stored at input location, save space +// 0x0 // output size = 0 bytes +// ) // ERROR + + +mstore(0x40, add(x,0x20)) // update free memory pointer +} + +// assembly { +// let x := mload(0x40) //Find empty storage location using "free memory pointer" +// mstore(x,sig) //Place signature at begining of empty storage +// mstore(add(x,0x04),a) //Place first argument directly next to signature +// mstore(add(x,0x24),b) //Place second argument next to first, padded to 32 bytes + +// let success := call( //This is the critical change (Pop the top stack value) +// 5000, //5k gas +// addr, //To addr +// 0, //No value +// x, /Inputs are stored at location x +// 0x44, //Inputs are 68 bytes long +// x, //Store output over input (saves space) +// 0x20) //Outputs are 32 bytes long + +// c := mload(x) //Assign output value to c +// mstore(0x40,add(x,0x44)) // Set storage pointer to empty space +// } + +} + +function trcTokenInMap(trcToken tokenId, uint256 tokenValue) returns(uint256 r) { +tokenCnt[tokenId] += tokenValue; +r = tokenCnt[tokenId]; +} + +function cntTokenTokenInMap(trcToken tokenId1, trcToken tokenId2, uint256 tokenValue) returns(trcToken r) { +cntTokenToken[tokenValue][tokenId1] = tokenId2; +r = cntTokenToken[tokenValue][tokenId1]; +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/addTrcToken002Cat.sol b/src/test/resources/soliditycode_v0.4.25/addTrcToken002Cat.sol new file mode 100644 index 00000000000..0858c6442fb --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/addTrcToken002Cat.sol @@ -0,0 +1,2017 @@ +//pragma solidity ^0.4.11; + + +/** + * @title Ownable + * @dev The Ownable contract has an owner address, and provides basic authorization control + * functions, this simplifies the implementation of "user permissions". + */ +contract Ownable { + address public owner; + + + /** + * @dev The Ownable constructor sets the original `owner` of the contract to the sender + * account. + */ + function Ownable() { + owner = msg.sender; + } + + + /** + * @dev Throws if called by any account other than the owner. + */ + modifier onlyOwner() { + require(msg.sender == owner); + _; + } + + + /** + * @dev Allows the current owner to transfer control of the contract to a newOwner. + * @param newOwner The address to transfer ownership to. + */ + function transferOwnership(address newOwner) onlyOwner { + if (newOwner != address(0)) { + owner = newOwner; + } + } + +} + + + +/// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens +/// @author Dieter Shirley (https://github.com/dete) +contract ERC721 { + // Required methods + function totalSupply() public view returns (uint256 total); + function balanceOf(address _owner) public view returns (uint256 balance); + function ownerOf(uint256 _tokenId) external view returns (address owner); + function approve(address _to, uint256 _tokenId) external; + function transfer(address _to, uint256 _tokenId) external; + function transferFrom(address _from, address _to, uint256 _tokenId) external; + + // Events + event Transfer(address from, address to, uint256 tokenId); + event Approval(address owner, address approved, uint256 tokenId); + + // Optional + // function name() public view returns (string name); + // function symbol() public view returns (string symbol); + // function tokensOfOwner(address _owner) external view returns (uint256[] tokenIds); + // function tokenMetadata(uint256 _tokenId, string _preferredTransport) public view returns (string infoUrl); + + // ERC-165 Compatibility (https://github.com/ethereum/EIPs/issues/165) + function supportsInterface(bytes4 _interfaceID) external view returns (bool); +} + + +// // Auction wrapper functions + + +// Auction wrapper functions + + + + + + + +/// @title SEKRETOOOO +contract GeneScienceInterface { + + function isGeneScience() public pure returns (bool){ + return true; + } + + /// @dev given genes of kitten 1 & 2, return a genetic combination - may have a random factor + /// @param genes1 genes of mom + /// @param genes2 genes of sire + /// @return the genes that are supposed to be passed down the child + function mixGenes(uint256 genes1, uint256 genes2, uint256 targetBlock) public pure returns (uint256){ + + return (genes1+genes2+targetBlock)/2; + + +} +} + + + + + + + +/// @title A facet of KittyCore that manages special access privileges. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. +contract KittyAccessControl { + // This facet controls access control for CryptoKitties. There are four roles managed here: + // + // - The CEO: The CEO can reassign other roles and change the addresses of our dependent smart + // contracts. It is also the only role that can unpause the smart contract. It is initially + // set to the address that created the smart contract in the KittyCore constructor. + // + // - The CFO: The CFO can withdraw funds from KittyCore and its auction contracts. + // + // - The COO: The COO can release gen0 kitties to auction, and mint promo cats. + // + // It should be noted that these roles are distinct without overlap in their access abilities, the + // abilities listed for each role above are exhaustive. In particular, while the CEO can assign any + // address to any role, the CEO address itself doesn't have the ability to act in those roles. This + // restriction is intentional so that we aren't tempted to use the CEO address frequently out of + // convenience. The less we use an address, the less likely it is that we somehow compromise the + // account. + + /// @dev Emited when contract is upgraded - See README.md for updgrade plan + event ContractUpgrade(address newContract); + + // The addresses of the accounts (or contracts) that can execute actions within each roles. + address public ceoAddress; + address public cfoAddress; + address public cooAddress; + + // @dev Keeps track whether the contract is paused. When that is true, most actions are blocked + bool public paused = false; + + /// @dev Access modifier for CEO-only functionality + modifier onlyCEO() { + require(msg.sender == ceoAddress); + _; + } + + /// @dev Access modifier for CFO-only functionality + modifier onlyCFO() { + require(msg.sender == cfoAddress); + _; + } + + /// @dev Access modifier for COO-only functionality + modifier onlyCOO() { + require(msg.sender == cooAddress); + _; + } + + modifier onlyCLevel() { + require( + msg.sender == cooAddress || + msg.sender == ceoAddress || + msg.sender == cfoAddress + ); + _; + } + + /// @dev Assigns a new address to act as the CEO. Only available to the current CEO. + /// @param _newCEO The address of the new CEO + function setCEO(address _newCEO) external onlyCEO { + require(_newCEO != address(0)); + + ceoAddress = _newCEO; + } + + /// @dev Assigns a new address to act as the CFO. Only available to the current CEO. + /// @param _newCFO The address of the new CFO + function setCFO(address _newCFO) external onlyCEO { + require(_newCFO != address(0)); + + cfoAddress = _newCFO; + } + + /// @dev Assigns a new address to act as the COO. Only available to the current CEO. + /// @param _newCOO The address of the new COO + function setCOO(address _newCOO) external onlyCEO { + require(_newCOO != address(0)); + + cooAddress = _newCOO; + } + + /*** Pausable functionality adapted from OpenZeppelin ***/ + + /// @dev Modifier to allow actions only when the contract IS NOT paused + modifier whenNotPaused() { + require(!paused); + _; + } + + /// @dev Modifier to allow actions only when the contract IS paused + modifier whenPaused { + require(paused); + _; + } + + /// @dev Called by any "C-level" role to pause the contract. Used only when + /// a bug or exploit is detected and we need to limit damage. + function pause() external onlyCLevel whenNotPaused { + paused = true; + } + + /// @dev Unpauses the smart contract. Can only be called by the CEO, since + /// one reason we may pause the contract is when CFO or COO accounts are + /// compromised. + /// @notice This is public rather than external so it can be called by + /// derived contracts. + function unpause() public onlyCEO whenPaused { + // can't unpause if contract was upgraded + paused = false; + } +} + + + + +/// @title Base contract for CryptoKitties. Holds all common structs, events and base variables. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. +contract KittyBase is KittyAccessControl { + /*** EVENTS ***/ + + /// @dev The Birth event is fired whenever a new kitten comes into existence. This obviously + /// includes any time a cat is created through the giveBirth method, but it is also called + /// when a new gen0 cat is created. + event Birth(address owner, uint256 kittyId, uint256 matronId, uint256 sireId, uint256 genes); + + /// @dev Transfer event as defined in current draft of ERC721. Emitted every time a kitten + /// ownership is assigned, including births. + event Transfer(address from, address to, uint256 tokenId); + + /*** DATA TYPES ***/ + + /// @dev The main Kitty struct. Every cat in CryptoKitties is represented by a copy + /// of this structure, so great care was taken to ensure that it fits neatly into + /// exactly two 256-bit words. Note that the order of the members in this structure + /// is important because of the byte-packing rules used by Ethereum. + /// Ref: http://solidity.readthedocs.io/en/develop/miscellaneous.html + struct Kitty { + // The Kitty's genetic code is packed into these 256-bits, the format is + // sooper-sekret! A cat's genes never change. + uint256 genes; + + // The timestamp from the block when this cat came into existence. + uint64 birthTime; + + // The minimum timestamp after which this cat can engage in breeding + // activities again. This same timestamp is used for the pregnancy + // timer (for matrons) as well as the siring cooldown. + uint64 cooldownEndBlock; + + // The ID of the parents of this kitty, set to 0 for gen0 cats. + // Note that using 32-bit unsigned integers limits us to a "mere" + // 4 billion cats. This number might seem small until you realize + // that Ethereum currently has a limit of about 500 million + // transactions per year! So, this definitely won't be a problem + // for several years (even as Ethereum learns to scale). + uint32 matronId; + uint32 sireId; + + // Set to the ID of the sire cat for matrons that are pregnant, + // zero otherwise. A non-zero value here is how we know a cat + // is pregnant. Used to retrieve the genetic material for the new + // kitten when the birth transpires. + uint32 siringWithId; + + // Set to the index in the cooldown array (see below) that represents + // the current cooldown duration for this Kitty. This starts at zero + // for gen0 cats, and is initialized to floor(generation/2) for others. + // Incremented by one for each successful breeding action, regardless + // of whether this cat is acting as matron or sire. + uint16 cooldownIndex; + + // The "generation number" of this cat. Cats minted by the CK contract + // for sale are called "gen0" and have a generation number of 0. The + // generation number of all other cats is the larger of the two generation + // numbers of their parents, plus one. + // (i.e. max(matron.generation, sire.generation) + 1) + uint16 generation; + } + + /*** CONSTANTS ***/ + + /// @dev A lookup table indicating the cooldown duration after any successful + /// breeding action, called "pregnancy time" for matrons and "siring cooldown" + /// for sires. Designed such that the cooldown roughly doubles each time a cat + /// is bred, encouraging owners not to just keep breeding the same cat over + /// and over again. Caps out at one week (a cat can breed an unbounded number + /// of times, and the maximum cooldown is always seven days). + uint32[14] public cooldowns = [ + uint32(1 minutes), + uint32(2 minutes), + uint32(5 minutes), + uint32(10 minutes), + uint32(30 minutes), + uint32(1 hours), + uint32(2 hours), + uint32(4 hours), + uint32(8 hours), + uint32(16 hours), + uint32(1 days), + uint32(2 days), + uint32(4 days), + uint32(7 days) + ]; + + // An approximation of currently how many seconds are in between blocks. + uint256 public secondsPerBlock = 15; + + /*** STORAGE ***/ + + /// @dev An array containing the Kitty struct for all Kitties in existence. The ID + /// of each cat is actually an index into this array. Note that ID 0 is a negacat, + /// the unKitty, the mythical beast that is the parent of all gen0 cats. A bizarre + /// creature that is both matron and sire... to itself! Has an invalid genetic code. + /// In other words, cat ID 0 is invalid... ;-) + Kitty[] kitties; + + /// @dev A mapping from cat IDs to the address that owns them. All cats have + /// some valid owner address, even gen0 cats are created with a non-zero owner. + mapping (uint256 => address) public kittyIndexToOwner; + + // @dev A mapping from owner address to count of tokens that address owns. + // Used internally inside balanceOf() to resolve ownership count. + mapping (address => uint256) ownershipTokenCount; + + /// @dev A mapping from KittyIDs to an address that has been approved to call + /// transferFrom(). Each Kitty can only have one approved address for transfer + /// at any time. A zero value means no approval is outstanding. + mapping (uint256 => address) public kittyIndexToApproved; + + /// @dev A mapping from KittyIDs to an address that has been approved to use + /// this Kitty for siring via breedWith(). Each Kitty can only have one approved + /// address for siring at any time. A zero value means no approval is outstanding. + mapping (uint256 => address) public sireAllowedToAddress; + + /// @dev The address of the ClockAuction contract that handles sales of Kitties. This + /// same contract handles both peer-to-peer sales as well as the gen0 sales which are + /// initiated every 15 minutes. + SaleClockAuction public saleAuction; + + /// @dev The address of a custom ClockAuction subclassed contract that handles siring + /// auctions. Needs to be separate from saleAuction because the actions taken on success + /// after a sales and siring auction are quite different. + SiringClockAuction public siringAuction; + + /// @dev Assigns ownership of a specific Kitty to an address. + function _transfer(address _from, address _to, uint256 _tokenId) internal { + // Since the number of kittens is capped to 2^32 we can't overflow this + ownershipTokenCount[_to]++; + // transfer ownership + kittyIndexToOwner[_tokenId] = _to; + // When creating new kittens _from is 0x0, but we can't account that address. + if (_from != address(0)) { + ownershipTokenCount[_from]--; + // once the kitten is transferred also clear sire allowances + delete sireAllowedToAddress[_tokenId]; + // clear any previously approved ownership exchange + delete kittyIndexToApproved[_tokenId]; + } + // Emit the transfer event. + Transfer(_from, _to, _tokenId); + } + + /// @dev An internal method that creates a new kitty and stores it. This + /// method doesn't do any checking and should only be called when the + /// input data is known to be valid. Will generate both a Birth event + /// and a Transfer event. + /// @param _matronId The kitty ID of the matron of this cat (zero for gen0) + /// @param _sireId The kitty ID of the sire of this cat (zero for gen0) + /// @param _generation The generation number of this cat, must be computed by caller. + /// @param _genes The kitty's genetic code. + /// @param _owner The inital owner of this cat, must be non-zero (except for the unKitty, ID 0) + function _createKitty( + uint256 _matronId, + uint256 _sireId, + uint256 _generation, + uint256 _genes, + address _owner + ) + internal + returns (uint) + { + // These requires are not strictly necessary, our calling code should make + // sure that these conditions are never broken. However! _createKitty() is already + // an expensive call (for storage), and it doesn't hurt to be especially careful + // to ensure our data structures are always valid. + require(_matronId == uint256(uint32(_matronId))); + require(_sireId == uint256(uint32(_sireId))); + require(_generation == uint256(uint16(_generation))); + + // New kitty starts with the same cooldown as parent gen/2 + uint16 cooldownIndex = uint16(_generation / 2); + if (cooldownIndex > 13) { + cooldownIndex = 13; + } + + Kitty memory _kitty = Kitty({ + genes: _genes, + birthTime: uint64(now), + cooldownEndBlock: 0, + matronId: uint32(_matronId), + sireId: uint32(_sireId), + siringWithId: 0, + cooldownIndex: cooldownIndex, + generation: uint16(_generation) + }); + uint256 newKittenId = kitties.push(_kitty) - 1; + + // It's probably never going to happen, 4 billion cats is A LOT, but + // let's just be 100% sure we never let this happen. + require(newKittenId == uint256(uint32(newKittenId))); + + // emit the birth event + Birth( + _owner, + newKittenId, + uint256(_kitty.matronId), + uint256(_kitty.sireId), + _kitty.genes + ); + + // This will assign ownership, and also emit the Transfer event as + // per ERC721 draft + _transfer(0, _owner, newKittenId); + + return newKittenId; + } + + // Any C-level can fix how many seconds per blocks are currently observed. + function setSecondsPerBlock(uint256 secs) external onlyCLevel { + require(secs < cooldowns[0]); + secondsPerBlock = secs; + } +} + + + + + +/// @title The external contract that is responsible for generating metadata for the kitties, +/// it has one function that will return the data as bytes. +contract ERC721Metadata { + /// @dev Given a token Id, returns a byte array that is supposed to be converted into string. + function getMetadata(uint256 _tokenId, string) public view returns (bytes32[4] buffer, uint256 count) { + if (_tokenId == 1) { + buffer[0] = "Hello World! :D"; + count = 15; + } else if (_tokenId == 2) { + buffer[0] = "I would definitely choose a medi"; + buffer[1] = "um length string."; + count = 49; + } else if (_tokenId == 3) { + buffer[0] = "Lorem ipsum dolor sit amet, mi e"; + buffer[1] = "st accumsan dapibus augue lorem,"; + buffer[2] = " tristique vestibulum id, libero"; + buffer[3] = " suscipit varius sapien aliquam."; + count = 128; + } + } +} + + +/// @title The facet of the CryptoKitties core contract that manages ownership, ERC-721 (draft) compliant. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev Ref: https://github.com/ethereum/EIPs/issues/721 +/// See the KittyCore contract documentation to understand how the various contract facets are arranged. +contract KittyOwnership is KittyBase, ERC721 { + + /// @notice Name and symbol of the non fungible token, as defined in ERC721. + string public constant name = "CryptoKitties"; + string public constant symbol = "CK"; + + // The contract that will return kitty metadata + ERC721Metadata public erc721Metadata; + + bytes4 constant InterfaceSignature_ERC165 = + bytes4(keccak256('supportsInterface(bytes4)')); + + bytes4 constant InterfaceSignature_ERC721 = + bytes4(keccak256('name()')) ^ + bytes4(keccak256('symbol()')) ^ + bytes4(keccak256('totalSupply()')) ^ + bytes4(keccak256('balanceOf(address)')) ^ + bytes4(keccak256('ownerOf(uint256)')) ^ + bytes4(keccak256('approve(address,uint256)')) ^ + bytes4(keccak256('transfer(address,uint256)')) ^ + bytes4(keccak256('transferFrom(address,address,uint256)')) ^ + bytes4(keccak256('tokensOfOwner(address)')) ^ + bytes4(keccak256('tokenMetadata(uint256,string)')); + + /// @notice Introspection interface as per ERC-165 (https://github.com/ethereum/EIPs/issues/165). + /// Returns true for any standardized interfaces implemented by this contract. We implement + /// ERC-165 (obviously!) and ERC-721. + function supportsInterface(bytes4 _interfaceID) external view returns (bool) + { + // DEBUG ONLY + //require((InterfaceSignature_ERC165 == 0x01ffc9a7) && (InterfaceSignature_ERC721 == 0x9a20483d)); + + return ((_interfaceID == InterfaceSignature_ERC165) || (_interfaceID == InterfaceSignature_ERC721)); + } + + /// @dev Set the address of the sibling contract that tracks metadata. + /// CEO only. + function setMetadataAddress(address _contractAddress) public onlyCEO { + erc721Metadata = ERC721Metadata(_contractAddress); + } + + // Internal utility functions: These functions all assume that their input arguments + // are valid. We leave it to public methods to sanitize their inputs and follow + // the required logic. + + /// @dev Checks if a given address is the current owner of a particular Kitty. + /// @param _claimant the address we are validating against. + /// @param _tokenId kitten id, only valid when > 0 + function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { + return kittyIndexToOwner[_tokenId] == _claimant; + } + + /// @dev Checks if a given address currently has transferApproval for a particular Kitty. + /// @param _claimant the address we are confirming kitten is approved for. + /// @param _tokenId kitten id, only valid when > 0 + function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) { + return kittyIndexToApproved[_tokenId] == _claimant; + } + + /// @dev Marks an address as being approved for transferFrom(), overwriting any previous + /// approval. Setting _approved to address(0) clears all transfer approval. + /// NOTE: _approve() does NOT send the Approval event. This is intentional because + /// _approve() and transferFrom() are used together for putting Kitties on auction, and + /// there is no value in spamming the log with Approval events in that case. + function _approve(uint256 _tokenId, address _approved) internal { + kittyIndexToApproved[_tokenId] = _approved; + } + + /// @notice Returns the number of Kitties owned by a specific address. + /// @param _owner The owner address to check. + /// @dev Required for ERC-721 compliance + function balanceOf(address _owner) public view returns (uint256 count) { + return ownershipTokenCount[_owner]; + } + + /// @notice Transfers a Kitty to another address. If transferring to a smart + /// contract be VERY CAREFUL to ensure that it is aware of ERC-721 (or + /// CryptoKitties specifically) or your Kitty may be lost forever. Seriously. + /// @param _to The address of the recipient, can be a user or contract. + /// @param _tokenId The ID of the Kitty to transfer. + /// @dev Required for ERC-721 compliance. + function transfer( + address _to, + uint256 _tokenId + ) + external + whenNotPaused + { + // Safety check to prevent against an unexpected 0x0 default. + require(_to != address(0)); + // Disallow transfers to this contract to prevent accidental misuse. + // The contract should never own any kitties (except very briefly + // after a gen0 cat is created and before it goes on auction). + require(_to != address(this)); + // Disallow transfers to the auction contracts to prevent accidental + // misuse. Auction contracts should only take ownership of kitties + // through the allow + transferFrom flow. + require(_to != address(saleAuction)); + require(_to != address(siringAuction)); + + // You can only send your own cat. + require(_owns(msg.sender, _tokenId)); + + // Reassign ownership, clear pending approvals, emit Transfer event. + _transfer(msg.sender, _to, _tokenId); + } + + /// @notice Grant another address the right to transfer a specific Kitty via + /// transferFrom(). This is the preferred flow for transfering NFTs to contracts. + /// @param _to The address to be granted transfer approval. Pass address(0) to + /// clear all approvals. + /// @param _tokenId The ID of the Kitty that can be transferred if this call succeeds. + /// @dev Required for ERC-721 compliance. + function approve( + address _to, + uint256 _tokenId + ) + external + whenNotPaused + { + // Only an owner can grant transfer approval. + require(_owns(msg.sender, _tokenId)); + + // Register the approval (replacing any previous approval). + _approve(_tokenId, _to); + + // Emit approval event. + Approval(msg.sender, _to, _tokenId); + } + + /// @notice Transfer a Kitty owned by another address, for which the calling address + /// has previously been granted transfer approval by the owner. + /// @param _from The address that owns the Kitty to be transfered. + /// @param _to The address that should take ownership of the Kitty. Can be any address, + /// including the caller. + /// @param _tokenId The ID of the Kitty to be transferred. + /// @dev Required for ERC-721 compliance. + function transferFrom( + address _from, + address _to, + uint256 _tokenId + ) + external + whenNotPaused + { + // Safety check to prevent against an unexpected 0x0 default. + require(_to != address(0)); + // Disallow transfers to this contract to prevent accidental misuse. + // The contract should never own any kitties (except very briefly + // after a gen0 cat is created and before it goes on auction). + require(_to != address(this)); + // Check for approval and valid ownership + require(_approvedFor(msg.sender, _tokenId)); + require(_owns(_from, _tokenId)); + + // Reassign ownership (also clears pending approvals and emits Transfer event). + _transfer(_from, _to, _tokenId); + } + + /// @notice Returns the total number of Kitties currently in existence. + /// @dev Required for ERC-721 compliance. + function totalSupply() public view returns (uint) { + return kitties.length - 1; + } + + /// @notice Returns the address currently assigned ownership of a given Kitty. + /// @dev Required for ERC-721 compliance. + function ownerOf(uint256 _tokenId) + external + view + returns (address owner) + { + owner = kittyIndexToOwner[_tokenId]; + + require(owner != address(0)); + } + + /// @notice Returns a list of all Kitty IDs assigned to an address. + /// @param _owner The owner whose Kitties we are interested in. + /// @dev This method MUST NEVER be called by smart contract code. First, it's fairly + /// expensive (it walks the entire Kitty array looking for cats belonging to owner), + /// but it also returns a dynamic array, which is only supported for web3 calls, and + /// not contract-to-contract calls. + function tokensOfOwner(address _owner) external view returns(uint256[] ownerTokens) { + uint256 tokenCount = balanceOf(_owner); + + if (tokenCount == 0) { + // Return an empty array + return new uint256[](0); + } else { + uint256[] memory result = new uint256[](tokenCount); + uint256 totalCats = totalSupply(); + uint256 resultIndex = 0; + + // We count on the fact that all cats have IDs starting at 1 and increasing + // sequentially up to the totalCat count. + uint256 catId; + + for (catId = 1; catId <= totalCats; catId++) { + if (kittyIndexToOwner[catId] == _owner) { + result[resultIndex] = catId; + resultIndex++; + } + } + + return result; + } + } + + /// @dev Adapted from memcpy() by @arachnid (Nick Johnson ) + /// This method is licenced under the Apache License. + /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol + function _memcpy(uint _dest, uint _src, uint _len) private view { + // Copy word-length chunks while possible + for(; _len >= 32; _len -= 32) { + assembly { + mstore(_dest, mload(_src)) + } + _dest += 32; + _src += 32; + } + + // Copy remaining bytes + uint256 mask = 256 ** (32 - _len) - 1; + assembly { + let srcpart := and(mload(_src), not(mask)) + let destpart := and(mload(_dest), mask) + mstore(_dest, or(destpart, srcpart)) + } + } + + /// @dev Adapted from toString(slice) by @arachnid (Nick Johnson ) + /// This method is licenced under the Apache License. + /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol + function _toString(bytes32[4] _rawBytes, uint256 _stringLength) private view returns (string) { + var outputString = new string(_stringLength); + uint256 outputPtr; + uint256 bytesPtr; + + assembly { + outputPtr := add(outputString, 32) + bytesPtr := _rawBytes + } + + _memcpy(outputPtr, bytesPtr, _stringLength); + + return outputString; + } + + /// @notice Returns a URI pointing to a metadata package for this token conforming to + /// ERC-721 (https://github.com/ethereum/EIPs/issues/721) + /// @param _tokenId The ID number of the Kitty whose metadata should be returned. + function tokenMetadata(uint256 _tokenId, string _preferredTransport) external view returns (string infoUrl) { + require(erc721Metadata != address(0)); + bytes32[4] memory buffer; + uint256 count; + (buffer, count) = erc721Metadata.getMetadata(_tokenId, _preferredTransport); + + return _toString(buffer, count); + } +} + + + +/// @title A facet of KittyCore that manages Kitty siring, gestation, and birth. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. +contract KittyBreeding is KittyOwnership { + + /// @dev The Pregnant event is fired when two cats successfully breed and the pregnancy + /// timer begins for the matron. + event Pregnant(address owner, uint256 matronId, uint256 sireId, uint256 cooldownEndBlock); + + /// @notice The minimum payment required to use breedWithAuto(). This fee goes towards + /// the gas cost paid by whatever calls giveBirth(), and can be dynamically updated by + /// the COO role as the gas price changes. + uint256 public autoBirthFee = 2 sun; + + // Keeps track of number of pregnant kitties. + uint256 public pregnantKitties; + + /// @dev The address of the sibling contract that is used to implement the sooper-sekret + /// genetic combination algorithm. + GeneScienceInterface public geneScience; + + /// @dev Update the address of the genetic contract, can only be called by the CEO. + /// @param _address An address of a GeneScience contract instance to be used from this point forward. + function setGeneScienceAddress(address _address) external onlyCEO { + GeneScienceInterface candidateContract = GeneScienceInterface(_address); + + // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 + require(candidateContract.isGeneScience()); + + // Set the new contract address + geneScience = candidateContract; + } + + /// @dev Checks that a given kitten is able to breed. Requires that the + /// current cooldown is finished (for sires) and also checks that there is + /// no pending pregnancy. + function _isReadyToBreed(Kitty _kit) internal view returns (bool) { + // In addition to checking the cooldownEndBlock, we also need to check to see if + // the cat has a pending birth; there can be some period of time between the end + // of the pregnacy timer and the birth event. + return (_kit.siringWithId == 0) && (_kit.cooldownEndBlock <= uint64(block.number)); + } + + /// @dev Check if a sire has authorized breeding with this matron. True if both sire + /// and matron have the same owner, or if the sire has given siring permission to + /// the matron's owner (via approveSiring()). + function _isSiringPermitted(uint256 _sireId, uint256 _matronId) internal view returns (bool) { + address matronOwner = kittyIndexToOwner[_matronId]; + address sireOwner = kittyIndexToOwner[_sireId]; + + // Siring is okay if they have same owner, or if the matron's owner was given + // permission to breed with this sire. + return (matronOwner == sireOwner || sireAllowedToAddress[_sireId] == matronOwner); + } + + /// @dev Set the cooldownEndTime for the given Kitty, based on its current cooldownIndex. + /// Also increments the cooldownIndex (unless it has hit the cap). + /// @param _kitten A reference to the Kitty in storage which needs its timer started. + function _triggerCooldown(Kitty storage _kitten) internal { + // Compute an estimation of the cooldown time in blocks (based on current cooldownIndex). + _kitten.cooldownEndBlock = uint64((cooldowns[_kitten.cooldownIndex]/secondsPerBlock) + block.number); + + // Increment the breeding count, clamping it at 13, which is the length of the + // cooldowns array. We could check the array size dynamically, but hard-coding + // this as a constant saves gas. Yay, Solidity! + if (_kitten.cooldownIndex < 13) { + _kitten.cooldownIndex += 1; + } + } + + /// @notice Grants approval to another user to sire with one of your Kitties. + /// @param _addr The address that will be able to sire with your Kitty. Set to + /// address(0) to clear all siring approvals for this Kitty. + /// @param _sireId A Kitty that you own that _addr will now be able to sire with. + function approveSiring(address _addr, uint256 _sireId) + external + whenNotPaused + { + require(_owns(msg.sender, _sireId)); + sireAllowedToAddress[_sireId] = _addr; + } + + /// @dev Updates the minimum payment required for calling giveBirthAuto(). Can only + /// be called by the COO address. (This fee is used to offset the gas cost incurred + /// by the autobirth daemon). + function setAutoBirthFee(uint256 val) external onlyCOO { + autoBirthFee = val; + } + + /// @dev Checks to see if a given Kitty is pregnant and (if so) if the gestation + /// period has passed. + function _isReadyToGiveBirth(Kitty _matron) private view returns (bool) { + return (_matron.siringWithId != 0) && (_matron.cooldownEndBlock <= uint64(block.number)); + } + + /// @notice Checks that a given kitten is able to breed (i.e. it is not pregnant or + /// in the middle of a siring cooldown). + /// @param _kittyId reference the id of the kitten, any user can inquire about it + function isReadyToBreed(uint256 _kittyId) + public + view + returns (bool) + { + require(_kittyId > 0); + Kitty storage kit = kitties[_kittyId]; + return _isReadyToBreed(kit); + } + + /// @dev Checks whether a kitty is currently pregnant. + /// @param _kittyId reference the id of the kitten, any user can inquire about it + function isPregnant(uint256 _kittyId) + public + view + returns (bool) + { + require(_kittyId > 0); + // A kitty is pregnant if and only if this field is set + return kitties[_kittyId].siringWithId != 0; + } + + /// @dev Internal check to see if a given sire and matron are a valid mating pair. DOES NOT + /// check ownership permissions (that is up to the caller). + /// @param _matron A reference to the Kitty struct of the potential matron. + /// @param _matronId The matron's ID. + /// @param _sire A reference to the Kitty struct of the potential sire. + /// @param _sireId The sire's ID + function _isValidMatingPair( + Kitty storage _matron, + uint256 _matronId, + Kitty storage _sire, + uint256 _sireId + ) + private + view + returns(bool) + { + // A Kitty can't breed with itself! + if (_matronId == _sireId) { + return false; + } + + // Kitties can't breed with their parents. + if (_matron.matronId == _sireId || _matron.sireId == _sireId) { + return false; + } + if (_sire.matronId == _matronId || _sire.sireId == _matronId) { + return false; + } + + // We can short circuit the sibling check (below) if either cat is + // gen zero (has a matron ID of zero). + if (_sire.matronId == 0 || _matron.matronId == 0) { + return true; + } + + // Kitties can't breed with full or half siblings. + if (_sire.matronId == _matron.matronId || _sire.matronId == _matron.sireId) { + return false; + } + if (_sire.sireId == _matron.matronId || _sire.sireId == _matron.sireId) { + return false; + } + + // Everything seems cool! Let's get DTF. + return true; + } + + /// @dev Internal check to see if a given sire and matron are a valid mating pair for + /// breeding via auction (i.e. skips ownership and siring approval checks). + function _canBreedWithViaAuction(uint256 _matronId, uint256 _sireId) + internal + view + returns (bool) + { + Kitty storage matron = kitties[_matronId]; + Kitty storage sire = kitties[_sireId]; + return _isValidMatingPair(matron, _matronId, sire, _sireId); + } + + /// @notice Checks to see if two cats can breed together, including checks for + /// ownership and siring approvals. Does NOT check that both cats are ready for + /// breeding (i.e. breedWith could still fail until the cooldowns are finished). + /// TODO: Shouldn't this check pregnancy and cooldowns?!? + /// @param _matronId The ID of the proposed matron. + /// @param _sireId The ID of the proposed sire. + function canBreedWith(uint256 _matronId, uint256 _sireId) + external + view + returns(bool) + { + require(_matronId > 0); + require(_sireId > 0); + Kitty storage matron = kitties[_matronId]; + Kitty storage sire = kitties[_sireId]; + return _isValidMatingPair(matron, _matronId, sire, _sireId) && + _isSiringPermitted(_sireId, _matronId); + } + + /// @dev Internal utility function to initiate breeding, assumes that all breeding + /// requirements have been checked. + function _breedWith(uint256 _matronId, uint256 _sireId) internal { + // Grab a reference to the Kitties from storage. + Kitty storage sire = kitties[_sireId]; + Kitty storage matron = kitties[_matronId]; + + // Mark the matron as pregnant, keeping track of who the sire is. + matron.siringWithId = uint32(_sireId); + + // Trigger the cooldown for both parents. + _triggerCooldown(sire); + _triggerCooldown(matron); + + // Clear siring permission for both parents. This may not be strictly necessary + // but it's likely to avoid confusion! + delete sireAllowedToAddress[_matronId]; + delete sireAllowedToAddress[_sireId]; + + // Every time a kitty gets pregnant, counter is incremented. + pregnantKitties++; + + // Emit the pregnancy event. + Pregnant(kittyIndexToOwner[_matronId], _matronId, _sireId, matron.cooldownEndBlock); + } + + /// @notice Breed a Kitty you own (as matron) with a sire that you own, or for which you + /// have previously been given Siring approval. Will either make your cat pregnant, or will + /// fail entirely. Requires a pre-payment of the fee given out to the first caller of giveBirth() + /// @param _matronId The ID of the Kitty acting as matron (will end up pregnant if successful) + /// @param _sireId The ID of the Kitty acting as sire (will begin its siring cooldown if successful) + function breedWithAuto(uint256 _matronId, uint256 _sireId) + external + payable + whenNotPaused + { + // Checks for payment. + require(msg.value >= autoBirthFee); + + // Caller must own the matron. + require(_owns(msg.sender, _matronId)); + + // Neither sire nor matron are allowed to be on auction during a normal + // breeding operation, but we don't need to check that explicitly. + // For matron: The caller of this function can't be the owner of the matron + // because the owner of a Kitty on auction is the auction house, and the + // auction house will never call breedWith(). + // For sire: Similarly, a sire on auction will be owned by the auction house + // and the act of transferring ownership will have cleared any oustanding + // siring approval. + // Thus we don't need to spend gas explicitly checking to see if either cat + // is on auction. + + // Check that matron and sire are both owned by caller, or that the sire + // has given siring permission to caller (i.e. matron's owner). + // Will fail for _sireId = 0 + require(_isSiringPermitted(_sireId, _matronId)); + + // Grab a reference to the potential matron + Kitty storage matron = kitties[_matronId]; + + // Make sure matron isn't pregnant, or in the middle of a siring cooldown + require(_isReadyToBreed(matron)); + + // Grab a reference to the potential sire + Kitty storage sire = kitties[_sireId]; + + // Make sure sire isn't pregnant, or in the middle of a siring cooldown + require(_isReadyToBreed(sire)); + + // Test that these cats are a valid mating pair. + require(_isValidMatingPair( + matron, + _matronId, + sire, + _sireId + )); + + // All checks passed, kitty gets pregnant! + _breedWith(_matronId, _sireId); + } + + /// @notice Have a pregnant Kitty give birth! + /// @param _matronId A Kitty ready to give birth. + /// @return The Kitty ID of the new kitten. + /// @dev Looks at a given Kitty and, if pregnant and if the gestation period has passed, + /// combines the genes of the two parents to create a new kitten. The new Kitty is assigned + /// to the current owner of the matron. Upon successful completion, both the matron and the + /// new kitten will be ready to breed again. Note that anyone can call this function (if they + /// are willing to pay the gas!), but the new kitten always goes to the mother's owner. + function giveBirth(uint256 _matronId) + external + whenNotPaused + returns(uint256) + { + // Grab a reference to the matron in storage. + Kitty storage matron = kitties[_matronId]; + + // Check that the matron is a valid cat. + require(matron.birthTime != 0); + + // Check that the matron is pregnant, and that its time has come! + require(_isReadyToGiveBirth(matron)); + + // Grab a reference to the sire in storage. + uint256 sireId = matron.siringWithId; + Kitty storage sire = kitties[sireId]; + + // Determine the higher generation number of the two parents + uint16 parentGen = matron.generation; + if (sire.generation > matron.generation) { + parentGen = sire.generation; + } + + // Call the sooper-sekret gene mixing operation. + uint256 childGenes = geneScience.mixGenes(matron.genes, sire.genes, matron.cooldownEndBlock - 1); + + // Make the new kitten! + address owner = kittyIndexToOwner[_matronId]; + uint256 kittenId = _createKitty(_matronId, matron.siringWithId, parentGen + 1, childGenes, owner); + + // Clear the reference to sire from the matron (REQUIRED! Having siringWithId + // set is what marks a matron as being pregnant.) + delete matron.siringWithId; + + // Every time a kitty gives birth counter is decremented. + pregnantKitties--; + + // Send the balance fee to the person who made birth happen. + msg.sender.send(autoBirthFee); + + // return the new kitten's ID + return kittenId; + } +} + + + + + + + + + + +/// @title Auction Core +/// @dev Contains models, variables, and internal methods for the auction. +/// @notice We omit a fallback function to prevent accidental sends to this contract. +contract ClockAuctionBase { + + // Represents an auction on an NFT + struct Auction { + // Current owner of NFT + address seller; + // Price (in wei) at beginning of auction + uint128 startingPrice; + // Price (in wei) at end of auction + uint128 endingPrice; + // Duration (in seconds) of auction + uint64 duration; + // Time when auction started + // NOTE: 0 if this auction has been concluded + uint64 startedAt; + } + + // Reference to contract tracking NFT ownership + ERC721 public nonFungibleContract; + + // Cut owner takes on each auction, measured in basis points (1/100 of a percent). + // Values 0-10,000 map to 0%-100% + uint256 public ownerCut; + + // Map from token ID to their corresponding auction. + mapping (uint256 => Auction) tokenIdToAuction; + + event AuctionCreated(uint256 tokenId, uint256 startingPrice, uint256 endingPrice, uint256 duration); + event AuctionSuccessful(uint256 tokenId, uint256 totalPrice, address winner); + event AuctionCancelled(uint256 tokenId); + + /// @dev Returns true if the claimant owns the token. + /// @param _claimant - Address claiming to own the token. + /// @param _tokenId - ID of token whose ownership to verify. + function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { + return (nonFungibleContract.ownerOf(_tokenId) == _claimant); + } + + /// @dev Escrows the NFT, assigning ownership to this contract. + /// Throws if the escrow fails. + /// @param _owner - Current owner address of token to escrow. + /// @param _tokenId - ID of token whose approval to verify. + function _escrow(address _owner, uint256 _tokenId) internal { + // it will throw if transfer fails + nonFungibleContract.transferFrom(_owner, this, _tokenId); + } + + /// @dev Transfers an NFT owned by this contract to another address. + /// Returns true if the transfer succeeds. + /// @param _receiver - Address to transfer NFT to. + /// @param _tokenId - ID of token to transfer. + function _transfer(address _receiver, uint256 _tokenId) internal { + // it will throw if transfer fails + nonFungibleContract.transfer(_receiver, _tokenId); + } + + /// @dev Adds an auction to the list of open auctions. Also fires the + /// AuctionCreated event. + /// @param _tokenId The ID of the token to be put on auction. + /// @param _auction Auction to add. + function _addAuction(uint256 _tokenId, Auction _auction) internal { + // Require that all auctions have a duration of + // at least one minute. (Keeps our math from getting hairy!) + require(_auction.duration >= 1 minutes); + + tokenIdToAuction[_tokenId] = _auction; + + AuctionCreated( + uint256(_tokenId), + uint256(_auction.startingPrice), + uint256(_auction.endingPrice), + uint256(_auction.duration) + ); + } + + /// @dev Cancels an auction unconditionally. + function _cancelAuction(uint256 _tokenId, address _seller) internal { + _removeAuction(_tokenId); + _transfer(_seller, _tokenId); + AuctionCancelled(_tokenId); + } + + /// @dev Computes the price and transfers winnings. + /// Does NOT transfer ownership of token. + function _bid(uint256 _tokenId, uint256 _bidAmount) + internal + returns (uint256) + { + // Get a reference to the auction struct + Auction storage auction = tokenIdToAuction[_tokenId]; + + // Explicitly check that this auction is currently live. + // (Because of how Ethereum mappings work, we can't just count + // on the lookup above failing. An invalid _tokenId will just + // return an auction object that is all zeros.) + require(_isOnAuction(auction)); + + // Check that the bid is greater than or equal to the current price + uint256 price = _currentPrice(auction); + require(_bidAmount >= price); + + // Grab a reference to the seller before the auction struct + // gets deleted. + address seller = auction.seller; + + // The bid is good! Remove the auction before sending the fees + // to the sender so we can't have a reentrancy attack. + _removeAuction(_tokenId); + + // Transfer proceeds to seller (if there are any!) + if (price > 0) { + // Calculate the auctioneer's cut. + // (NOTE: _computeCut() is guaranteed to return a + // value <= price, so this subtraction can't go negative.) + uint256 auctioneerCut = _computeCut(price); + uint256 sellerProceeds = price - auctioneerCut; + + // NOTE: Doing a transfer() in the middle of a complex + // method like this is generally discouraged because of + // reentrancy attacks and DoS attacks if the seller is + // a contract with an invalid fallback function. We explicitly + // guard against reentrancy attacks by removing the auction + // before calling transfer(), and the only thing the seller + // can DoS is the sale of their own asset! (And if it's an + // accident, they can call cancelAuction(). ) + seller.transfer(sellerProceeds); + } + + // Calculate any excess funds included with the bid. If the excess + // is anything worth worrying about, transfer it back to bidder. + // NOTE: We checked above that the bid amount is greater than or + // equal to the price so this cannot underflow. + uint256 bidExcess = _bidAmount - price; + + // Return the funds. Similar to the previous transfer, this is + // not susceptible to a re-entry attack because the auction is + // removed before any transfers occur. + msg.sender.transfer(bidExcess); + + // Tell the world! + AuctionSuccessful(_tokenId, price, msg.sender); + + return price; + } + + /// @dev Removes an auction from the list of open auctions. + /// @param _tokenId - ID of NFT on auction. + function _removeAuction(uint256 _tokenId) internal { + delete tokenIdToAuction[_tokenId]; + } + + /// @dev Returns true if the NFT is on auction. + /// @param _auction - Auction to check. + function _isOnAuction(Auction storage _auction) internal view returns (bool) { + return (_auction.startedAt > 0); + } + + /// @dev Returns current price of an NFT on auction. Broken into two + /// functions (this one, that computes the duration from the auction + /// structure, and the other that does the price computation) so we + /// can easily test that the price computation works correctly. + function _currentPrice(Auction storage _auction) + internal + view + returns (uint256) + { + uint256 secondsPassed = 0; + + // A bit of insurance against negative values (or wraparound). + // Probably not necessary (since Ethereum guarnatees that the + // now variable doesn't ever go backwards). + if (now > _auction.startedAt) { + secondsPassed = now - _auction.startedAt; + } + + return _computeCurrentPrice( + _auction.startingPrice, + _auction.endingPrice, + _auction.duration, + secondsPassed + ); + } + + /// @dev Computes the current price of an auction. Factored out + /// from _currentPrice so we can run extensive unit tests. + /// When testing, make this function public and turn on + /// `Current price computation` test suite. + function _computeCurrentPrice( + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration, + uint256 _secondsPassed + ) + internal + pure + returns (uint256) + { + // NOTE: We don't use SafeMath (or similar) in this function because + // all of our public functions carefully cap the maximum values for + // time (at 64-bits) and currency (at 128-bits). _duration is + // also known to be non-zero (see the require() statement in + // _addAuction()) + if (_secondsPassed >= _duration) { + // We've reached the end of the dynamic pricing portion + // of the auction, just return the end price. + return _endingPrice; + } else { + // Starting price can be higher than ending price (and often is!), so + // this delta can be negative. + int256 totalPriceChange = int256(_endingPrice) - int256(_startingPrice); + + // This multiplication can't overflow, _secondsPassed will easily fit within + // 64-bits, and totalPriceChange will easily fit within 128-bits, their product + // will always fit within 256-bits. + int256 currentPriceChange = totalPriceChange * int256(_secondsPassed) / int256(_duration); + + // currentPriceChange can be negative, but if so, will have a magnitude + // less that _startingPrice. Thus, this result will always end up positive. + int256 currentPrice = int256(_startingPrice) + currentPriceChange; + + return uint256(currentPrice); + } + } + + /// @dev Computes owner's cut of a sale. + /// @param _price - Sale price of NFT. + function _computeCut(uint256 _price) internal view returns (uint256) { + // NOTE: We don't use SafeMath (or similar) in this function because + // all of our entry functions carefully cap the maximum values for + // currency (at 128-bits), and ownerCut <= 10000 (see the require() + // statement in the ClockAuction constructor). The result of this + // function is always guaranteed to be <= _price. + return _price * ownerCut / 10000; + } + +} + + + + + + + +/** + * @title Pausable + * @dev Base contract which allows children to implement an emergency stop mechanism. + */ +contract Pausable is Ownable { + event Pause(); + event Unpause(); + + bool public paused = false; + + + /** + * @dev modifier to allow actions only when the contract IS paused + */ + modifier whenNotPaused() { + require(!paused); + _; + } + + /** + * @dev modifier to allow actions only when the contract IS NOT paused + */ + modifier whenPaused { + require(paused); + _; + } + + /** + * @dev called by the owner to pause, triggers stopped state + */ + function pause() onlyOwner whenNotPaused returns (bool) { + paused = true; + Pause(); + return true; + } + + /** + * @dev called by the owner to unpause, returns to normal state + */ + function unpause() onlyOwner whenPaused returns (bool) { + paused = false; + Unpause(); + return true; + } +} + + +/// @title Clock auction for non-fungible tokens. +/// @notice We omit a fallback function to prevent accidental sends to this contract. +contract ClockAuction is Pausable, ClockAuctionBase { + + /// @dev The ERC-165 interface signature for ERC-721. + /// Ref: https://github.com/ethereum/EIPs/issues/165 + /// Ref: https://github.com/ethereum/EIPs/issues/721 + bytes4 constant InterfaceSignature_ERC721 = bytes4(0x9a20483d); + + /// @dev Constructor creates a reference to the NFT ownership contract + /// and verifies the owner cut is in the valid range. + /// @param _nftAddress - address of a deployed contract implementing + /// the Nonfungible Interface. + /// @param _cut - percent cut the owner takes on each auction, must be + /// between 0-10,000. + function ClockAuction(address _nftAddress, uint256 _cut) public { + require(_cut <= 10000); + ownerCut = _cut; + + ERC721 candidateContract = ERC721(_nftAddress); + require(candidateContract.supportsInterface(InterfaceSignature_ERC721)); + nonFungibleContract = candidateContract; + } + + /// @dev Remove all Ether from the contract, which is the owner's cuts + /// as well as any Ether sent directly to the contract address. + /// Always transfers to the NFT contract, but can be called either by + /// the owner or the NFT contract. + function withdrawBalance() external { + address nftAddress = address(nonFungibleContract); + + require( + msg.sender == owner || + msg.sender == nftAddress + ); + // We are using this boolean method to make sure that even if one fails it will still work + bool res = nftAddress.send(this.balance); + } + + /// @dev Creates and begins a new auction. + /// @param _tokenId - ID of token to auction, sender must be owner. + /// @param _startingPrice - Price of item (in wei) at beginning of auction. + /// @param _endingPrice - Price of item (in wei) at end of auction. + /// @param _duration - Length of time to move between starting + /// price and ending price (in seconds). + /// @param _seller - Seller, if not the message sender + function createAuction( + uint256 _tokenId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration, + address _seller + ) + external + whenNotPaused + { + // Sanity check that no inputs overflow how many bits we've allocated + // to store them in the auction struct. + require(_startingPrice == uint256(uint128(_startingPrice))); + require(_endingPrice == uint256(uint128(_endingPrice))); + require(_duration == uint256(uint64(_duration))); + + require(_owns(msg.sender, _tokenId)); + _escrow(msg.sender, _tokenId); + Auction memory auction = Auction( + _seller, + uint128(_startingPrice), + uint128(_endingPrice), + uint64(_duration), + uint64(now) + ); + _addAuction(_tokenId, auction); + } + + /// @dev Bids on an open auction, completing the auction and transferring + /// ownership of the NFT if enough Ether is supplied. + /// @param _tokenId - ID of token to bid on. + function bid(uint256 _tokenId) + external + payable + whenNotPaused + { + // _bid will throw if the bid or funds transfer fails + _bid(_tokenId, msg.value); + _transfer(msg.sender, _tokenId); + } + + /// @dev Cancels an auction that hasn't been won yet. + /// Returns the NFT to original owner. + /// @notice This is a state-modifying function that can + /// be called while the contract is paused. + /// @param _tokenId - ID of token on auction + function cancelAuction(uint256 _tokenId) + external + { + Auction storage auction = tokenIdToAuction[_tokenId]; + require(_isOnAuction(auction)); + address seller = auction.seller; + require(msg.sender == seller); + _cancelAuction(_tokenId, seller); + } + + /// @dev Cancels an auction when the contract is paused. + /// Only the owner may do this, and NFTs are returned to + /// the seller. This should only be used in emergencies. + /// @param _tokenId - ID of the NFT on auction to cancel. + function cancelAuctionWhenPaused(uint256 _tokenId) + whenPaused + onlyOwner + external + { + Auction storage auction = tokenIdToAuction[_tokenId]; + require(_isOnAuction(auction)); + _cancelAuction(_tokenId, auction.seller); + } + + /// @dev Returns auction info for an NFT on auction. + /// @param _tokenId - ID of NFT on auction. + function getAuction(uint256 _tokenId) + external + view + returns + ( + address seller, + uint256 startingPrice, + uint256 endingPrice, + uint256 duration, + uint256 startedAt + ) { + Auction storage auction = tokenIdToAuction[_tokenId]; + require(_isOnAuction(auction)); + return ( + auction.seller, + auction.startingPrice, + auction.endingPrice, + auction.duration, + auction.startedAt + ); + } + + /// @dev Returns the current price of an auction. + /// @param _tokenId - ID of the token price we are checking. + function getCurrentPrice(uint256 _tokenId) + external + view + returns (uint256) + { + Auction storage auction = tokenIdToAuction[_tokenId]; + require(_isOnAuction(auction)); + return _currentPrice(auction); + } + +} + + +/// @title Reverse auction modified for siring +/// @notice We omit a fallback function to prevent accidental sends to this contract. +contract SiringClockAuction is ClockAuction { + + // @dev Sanity check that allows us to ensure that we are pointing to the + // right auction in our setSiringAuctionAddress() call. + bool public isSiringClockAuction = true; + + // Delegate constructor + function SiringClockAuction(address _nftAddr, uint256 _cut) public + ClockAuction(_nftAddr, _cut) {} + + /// @dev Creates and begins a new auction. Since this function is wrapped, + /// require sender to be KittyCore contract. + /// @param _tokenId - ID of token to auction, sender must be owner. + /// @param _startingPrice - Price of item (in wei) at beginning of auction. + /// @param _endingPrice - Price of item (in wei) at end of auction. + /// @param _duration - Length of auction (in seconds). + /// @param _seller - Seller, if not the message sender + function createAuction( + uint256 _tokenId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration, + address _seller + ) + external + { + // Sanity check that no inputs overflow how many bits we've allocated + // to store them in the auction struct. + require(_startingPrice == uint256(uint128(_startingPrice))); + require(_endingPrice == uint256(uint128(_endingPrice))); + require(_duration == uint256(uint64(_duration))); + + require(msg.sender == address(nonFungibleContract)); + _escrow(_seller, _tokenId); + Auction memory auction = Auction( + _seller, + uint128(_startingPrice), + uint128(_endingPrice), + uint64(_duration), + uint64(now) + ); + _addAuction(_tokenId, auction); + } + + /// @dev Places a bid for siring. Requires the sender + /// is the KittyCore contract because all bid methods + /// should be wrapped. Also returns the kitty to the + /// seller rather than the winner. + function bid(uint256 _tokenId) + external + payable + { + require(msg.sender == address(nonFungibleContract)); + address seller = tokenIdToAuction[_tokenId].seller; + // _bid checks that token ID is valid and will throw if bid fails + _bid(_tokenId, msg.value); + // We transfer the kitty back to the seller, the winner will get + // the offspring + _transfer(seller, _tokenId); + } + +} + + + + + +/// @title Clock auction modified for sale of kitties +/// @notice We omit a fallback function to prevent accidental sends to this contract. +contract SaleClockAuction is ClockAuction { + + // @dev Sanity check that allows us to ensure that we are pointing to the + // right auction in our setSaleAuctionAddress() call. + bool public isSaleClockAuction = true; + + // Tracks last 5 sale price of gen0 kitty sales + uint256 public gen0SaleCount; + uint256[5] public lastGen0SalePrices; + + // Delegate constructor + function SaleClockAuction(address _nftAddr, uint256 _cut) public + ClockAuction(_nftAddr, _cut) {} + + /// @dev Creates and begins a new auction. + /// @param _tokenId - ID of token to auction, sender must be owner. + /// @param _startingPrice - Price of item (in wei) at beginning of auction. + /// @param _endingPrice - Price of item (in wei) at end of auction. + /// @param _duration - Length of auction (in seconds). + /// @param _seller - Seller, if not the message sender + function createAuction( + uint256 _tokenId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration, + address _seller + ) + external + { + // Sanity check that no inputs overflow how many bits we've allocated + // to store them in the auction struct. + require(_startingPrice == uint256(uint128(_startingPrice))); + require(_endingPrice == uint256(uint128(_endingPrice))); + require(_duration == uint256(uint64(_duration))); + + require(msg.sender == address(nonFungibleContract)); + _escrow(_seller, _tokenId); + Auction memory auction = Auction( + _seller, + uint128(_startingPrice), + uint128(_endingPrice), + uint64(_duration), + uint64(now) + ); + _addAuction(_tokenId, auction); + } + + /// @dev Updates lastSalePrice if seller is the nft contract + /// Otherwise, works the same as default bid method. + function bid(uint256 _tokenId) + external + payable + { + // _bid verifies token ID size + address seller = tokenIdToAuction[_tokenId].seller; + uint256 price = _bid(_tokenId, msg.value); + _transfer(msg.sender, _tokenId); + + // If not a gen0 auction, exit + if (seller == address(nonFungibleContract)) { + // Track gen0 sale prices + lastGen0SalePrices[gen0SaleCount % 5] = price; + gen0SaleCount++; + } + } + + function averageGen0SalePrice() external view returns (uint256) { + uint256 sum = 0; + for (uint256 i = 0; i < 5; i++) { + sum += lastGen0SalePrices[i]; + } + return sum / 5; + } + +} + + +/// @title Handles creating auctions for sale and siring of kitties. +/// This wrapper of ReverseAuction exists only so that users can create +/// auctions with only one transaction. +contract KittyAuction is KittyBreeding { + + // @notice The auction contract variables are defined in KittyBase to allow + // us to refer to them in KittyOwnership to prevent accidental transfers. + // `saleAuction` refers to the auction for gen0 and p2p sale of kitties. + // `siringAuction` refers to the auction for siring rights of kitties. + + /// @dev Sets the reference to the sale auction. + /// @param _address - Address of sale contract. + function setSaleAuctionAddress(address _address) external onlyCEO { + SaleClockAuction candidateContract = SaleClockAuction(_address); + + // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 + require(candidateContract.isSaleClockAuction()); + + // Set the new contract address + saleAuction = candidateContract; + } + + /// @dev Sets the reference to the siring auction. + /// @param _address - Address of siring contract. + function setSiringAuctionAddress(address _address) external onlyCEO { + SiringClockAuction candidateContract = SiringClockAuction(_address); + + // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 + require(candidateContract.isSiringClockAuction()); + + // Set the new contract address + siringAuction = candidateContract; + } + + /// @dev Put a kitty up for auction. + /// Does some ownership trickery to create auctions in one tx. + function createSaleAuction( + uint256 _kittyId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration + ) + external + whenNotPaused + { + // Auction contract checks input sizes + // If kitty is already on any auction, this will throw + // because it will be owned by the auction contract. + require(_owns(msg.sender, _kittyId)); + // Ensure the kitty is not pregnant to prevent the auction + // contract accidentally receiving ownership of the child. + // NOTE: the kitty IS allowed to be in a cooldown. + require(!isPregnant(_kittyId)); + _approve(_kittyId, saleAuction); + // Sale auction throws if inputs are invalid and clears + // transfer and sire approval after escrowing the kitty. + saleAuction.createAuction( + _kittyId, + _startingPrice, + _endingPrice, + _duration, + msg.sender + ); + } + + /// @dev Put a kitty up for auction to be sire. + /// Performs checks to ensure the kitty can be sired, then + /// delegates to reverse auction. + function createSiringAuction( + uint256 _kittyId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration + ) + external + whenNotPaused + { + // Auction contract checks input sizes + // If kitty is already on any auction, this will throw + // because it will be owned by the auction contract. + require(_owns(msg.sender, _kittyId)); + require(isReadyToBreed(_kittyId)); + _approve(_kittyId, siringAuction); + // Siring auction throws if inputs are invalid and clears + // transfer and sire approval after escrowing the kitty. + siringAuction.createAuction( + _kittyId, + _startingPrice, + _endingPrice, + _duration, + msg.sender + ); + } + + /// @dev Completes a siring auction by bidding. + /// Immediately breeds the winning matron with the sire on auction. + /// @param _sireId - ID of the sire on auction. + /// @param _matronId - ID of the matron owned by the bidder. + function bidOnSiringAuction( + uint256 _sireId, + uint256 _matronId + ) + external + payable + whenNotPaused + { + // Auction contract checks input sizes + require(_owns(msg.sender, _matronId)); + require(isReadyToBreed(_matronId)); + require(_canBreedWithViaAuction(_matronId, _sireId)); + + // Define the current price of the auction. + uint256 currentPrice = siringAuction.getCurrentPrice(_sireId); + require(msg.value >= currentPrice + autoBirthFee); + + // Siring auction will throw if the bid fails. + siringAuction.bid.value(msg.value - autoBirthFee)(_sireId); + _breedWith(uint32(_matronId), uint32(_sireId)); + } + + /// @dev Transfers the balance of the sale auction contract + /// to the KittyCore contract. We use two-step withdrawal to + /// prevent two transfer calls in the auction bid function. + function withdrawAuctionBalances() external onlyCLevel { + saleAuction.withdrawBalance(); + siringAuction.withdrawBalance(); + } +} + + +/// @title all functions related to creating kittens +contract KittyMinting is KittyAuction { + + // Limits the number of cats the contract owner can ever create. + uint256 public constant PROMO_CREATION_LIMIT = 5000; + uint256 public constant GEN0_CREATION_LIMIT = 45000; + + // Constants for gen0 auctions. + uint256 public constant GEN0_STARTING_PRICE = 10 sun; + uint256 public constant GEN0_AUCTION_DURATION = 1 days; + + // Counts the number of cats the contract owner has created. + uint256 public promoCreatedCount; + uint256 public gen0CreatedCount; + + /// @dev we can create promo kittens, up to a limit. Only callable by COO + /// @param _genes the encoded genes of the kitten to be created, any value is accepted + /// @param _owner the future owner of the created kittens. Default to contract COO + function createPromoKitty(uint256 _genes, address _owner) external onlyCOO { + address kittyOwner = _owner; + if (kittyOwner == address(0)) { + kittyOwner = cooAddress; + } + require(promoCreatedCount < PROMO_CREATION_LIMIT); + + promoCreatedCount++; + _createKitty(0, 0, 0, _genes, kittyOwner); + } + + /// @dev Creates a new gen0 kitty with the given genes and + /// creates an auction for it. + function createGen0Auction(uint256 _genes) external onlyCOO { + require(gen0CreatedCount < GEN0_CREATION_LIMIT); + + uint256 kittyId = _createKitty(0, 0, 0, _genes, address(this)); + _approve(kittyId, saleAuction); + + saleAuction.createAuction( + kittyId, + _computeNextGen0Price(), + 0, + GEN0_AUCTION_DURATION, + address(this) + ); + + gen0CreatedCount++; + } + + /// @dev Computes the next gen0 auction starting price, given + /// the average of the past 5 prices + 50%. + function _computeNextGen0Price() internal view returns (uint256) { + uint256 avePrice = saleAuction.averageGen0SalePrice(); + + // Sanity check to ensure we don't overflow arithmetic + require(avePrice == uint256(uint128(avePrice))); + + uint256 nextPrice = avePrice + (avePrice / 2); + + // We never auction for less than starting price + if (nextPrice < GEN0_STARTING_PRICE) { + nextPrice = GEN0_STARTING_PRICE; + } + + return nextPrice; + } +} + + +/// @title CryptoKitties: Collectible, breedable, and oh-so-adorable cats on the Ethereum blockchain. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev The main CryptoKitties contract, keeps track of kittens so they don't wander around and get lost. +contract KittyCore is KittyMinting { + + // This is the main CryptoKitties contract. In order to keep our code seperated into logical sections, + // we've broken it up in two ways. First, we have several seperately-instantiated sibling contracts + // that handle auctions and our super-top-secret genetic combination algorithm. The auctions are + // seperate since their logic is somewhat complex and there's always a risk of subtle bugs. By keeping + // them in their own contracts, we can upgrade them without disrupting the main contract that tracks + // kitty ownership. The genetic combination algorithm is kept seperate so we can open-source all of + // the rest of our code without making it _too_ easy for folks to figure out how the genetics work. + // Don't worry, I'm sure someone will reverse engineer it soon enough! + // + // Secondly, we break the core contract into multiple files using inheritence, one for each major + // facet of functionality of CK. This allows us to keep related code bundled together while still + // avoiding a single giant file with everything in it. The breakdown is as follows: + // + // - KittyBase: This is where we define the most fundamental code shared throughout the core + // functionality. This includes our main data storage, constants and data types, plus + // internal functions for managing these items. + // + // - KittyAccessControl: This contract manages the various addresses and constraints for operations + // that can be executed only by specific roles. Namely CEO, CFO and COO. + // + // - KittyOwnership: This provides the methods required for basic non-fungible token + // transactions, following the draft ERC-721 spec (https://github.com/ethereum/EIPs/issues/721). + // + // - KittyBreeding: This file contains the methods necessary to breed cats together, including + // keeping track of siring offers, and relies on an external genetic combination contract. + // + // - KittyAuctions: Here we have the public methods for auctioning or bidding on cats or siring + // services. The actual auction functionality is handled in two sibling contracts (one + // for sales and one for siring), while auction creation and bidding is mostly mediated + // through this facet of the core contract. + // + // - KittyMinting: This final facet contains the functionality we use for creating new gen0 cats. + // We can make up to 5000 "promo" cats that can be given away (especially important when + // the community is new), and all others can only be created and then immediately put up + // for auction via an algorithmically determined starting price. Regardless of how they + // are created, there is a hard limit of 50k gen0 cats. After that, it's all up to the + // community to breed, breed, breed! + + // Set in case the core contract is broken and an upgrade is required + address public newContractAddress; + + /// @notice Creates the main CryptoKitties smart contract instance. + function KittyCore() public { + // Starts paused. + paused = true; + + // the creator of the contract is the initial CEO + ceoAddress = msg.sender; + + // the creator of the contract is also the initial COO + cooAddress = msg.sender; + + // start with the mythical kitten 0 - so we don't have generation-0 parent issues + _createKitty(0, 0, 0, uint256(-1), address(0)); + } + + /// @dev Used to mark the smart contract as upgraded, in case there is a serious + /// breaking bug. This method does nothing but keep track of the new contract and + /// emit a message indicating that the new address is set. It's up to clients of this + /// contract to update to the new contract address in that case. (This contract will + /// be paused indefinitely if such an upgrade takes place.) + /// @param _v2Address new address + function setNewAddress(address _v2Address) external onlyCEO whenPaused { + // See README.md for updgrade plan + newContractAddress = _v2Address; + ContractUpgrade(_v2Address); + } + + /// @notice No tipping! + /// @dev Reject all Ether from being sent here, unless it's from one of the + /// two auction contracts. (Hopefully, we can prevent user accidents.) + function() external payable { + require( + msg.sender == address(saleAuction) || + msg.sender == address(siringAuction) + ); + } + + /// @notice Returns all the relevant information about a specific kitty. + /// @param _id The ID of the kitty of interest. + function getKitty(uint256 _id) + external + view + returns ( + bool isGestating, + bool isReady, + uint256 cooldownIndex, + uint256 nextActionAt, + uint256 siringWithId, + uint256 birthTime, + uint256 matronId, + uint256 sireId, + uint256 generation, + uint256 genes + ) { + Kitty storage kit = kitties[_id]; + + // if this variable is 0 then it's not gestating + isGestating = (kit.siringWithId != 0); + isReady = (kit.cooldownEndBlock <= block.number); + cooldownIndex = uint256(kit.cooldownIndex); + nextActionAt = uint256(kit.cooldownEndBlock); + siringWithId = uint256(kit.siringWithId); + birthTime = uint256(kit.birthTime); + matronId = uint256(kit.matronId); + sireId = uint256(kit.sireId); + generation = uint256(kit.generation); + genes = kit.genes; + } + + /// @dev Override unpause so it requires all external contract addresses + /// to be set before contract can be unpaused. Also, we can't have + /// newContractAddress set either, because then the contract was upgraded. + /// @notice This is public rather than external so we can call super.unpause + /// without using an expensive CALL. + function unpause(address toAddress, uint256 tokenValue, trcToken tokenId) public onlyCEO whenPaused returns (uint256 r) { + require(saleAuction != address(0)); + require(siringAuction != address(0)); + require(geneScience != address(0)); + require(newContractAddress == address(0)); + toAddress.transferToken(tokenValue, tokenId); + r = address(this).tokenBalance(tokenId); + // Actually unpause the contract. + super.unpause(); + } + + // @dev Allows the CFO to capture the balance available to the contract. + function withdrawBalance() external onlyCFO { + uint256 balance = this.balance; + // Subtract all the currently pregnant kittens we have, plus 1 of margin. + uint256 subtractFees = (pregnantKitties + 1) * autoBirthFee; + + if (balance > subtractFees) { + cfoAddress.send(balance - subtractFees); + } + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/addTrcToken002Cat_withFinny.sol b/src/test/resources/soliditycode_v0.4.25/addTrcToken002Cat_withFinny.sol new file mode 100644 index 00000000000..5839b983a32 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/addTrcToken002Cat_withFinny.sol @@ -0,0 +1,2017 @@ +//pragma solidity ^0.4.11; + + +/** + * @title Ownable + * @dev The Ownable contract has an owner address, and provides basic authorization control + * functions, this simplifies the implementation of "user permissions". + */ +contract Ownable { + address public owner; + + + /** + * @dev The Ownable constructor sets the original `owner` of the contract to the sender + * account. + */ + function Ownable() { + owner = msg.sender; + } + + + /** + * @dev Throws if called by any account other than the owner. + */ + modifier onlyOwner() { + require(msg.sender == owner); + _; + } + + + /** + * @dev Allows the current owner to transfer control of the contract to a newOwner. + * @param newOwner The address to transfer ownership to. + */ + function transferOwnership(address newOwner) onlyOwner { + if (newOwner != address(0)) { + owner = newOwner; + } + } + +} + + + +/// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens +/// @author Dieter Shirley (https://github.com/dete) +contract ERC721 { + // Required methods + function totalSupply() public view returns (uint256 total); + function balanceOf(address _owner) public view returns (uint256 balance); + function ownerOf(uint256 _tokenId) external view returns (address owner); + function approve(address _to, uint256 _tokenId) external; + function transfer(address _to, uint256 _tokenId) external; + function transferFrom(address _from, address _to, uint256 _tokenId) external; + + // Events + event Transfer(address from, address to, uint256 tokenId); + event Approval(address owner, address approved, uint256 tokenId); + + // Optional + // function name() public view returns (string name); + // function symbol() public view returns (string symbol); + // function tokensOfOwner(address _owner) external view returns (uint256[] tokenIds); + // function tokenMetadata(uint256 _tokenId, string _preferredTransport) public view returns (string infoUrl); + + // ERC-165 Compatibility (https://github.com/ethereum/EIPs/issues/165) + function supportsInterface(bytes4 _interfaceID) external view returns (bool); +} + + +// // Auction wrapper functions + + +// Auction wrapper functions + + + + + + + +/// @title SEKRETOOOO +contract GeneScienceInterface { + + function isGeneScience() public pure returns (bool){ + return true; + } + + /// @dev given genes of kitten 1 & 2, return a genetic combination - may have a random factor + /// @param genes1 genes of mom + /// @param genes2 genes of sire + /// @return the genes that are supposed to be passed down the child + function mixGenes(uint256 genes1, uint256 genes2, uint256 targetBlock) public pure returns (uint256){ + + return (genes1+genes2+targetBlock)/2; + + +} +} + + + + + + + +/// @title A facet of KittyCore that manages special access privileges. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. +contract KittyAccessControl { + // This facet controls access control for CryptoKitties. There are four roles managed here: + // + // - The CEO: The CEO can reassign other roles and change the addresses of our dependent smart + // contracts. It is also the only role that can unpause the smart contract. It is initially + // set to the address that created the smart contract in the KittyCore constructor. + // + // - The CFO: The CFO can withdraw funds from KittyCore and its auction contracts. + // + // - The COO: The COO can release gen0 kitties to auction, and mint promo cats. + // + // It should be noted that these roles are distinct without overlap in their access abilities, the + // abilities listed for each role above are exhaustive. In particular, while the CEO can assign any + // address to any role, the CEO address itself doesn't have the ability to act in those roles. This + // restriction is intentional so that we aren't tempted to use the CEO address frequently out of + // convenience. The less we use an address, the less likely it is that we somehow compromise the + // account. + + /// @dev Emited when contract is upgraded - See README.md for updgrade plan + event ContractUpgrade(address newContract); + + // The addresses of the accounts (or contracts) that can execute actions within each roles. + address public ceoAddress; + address public cfoAddress; + address public cooAddress; + + // @dev Keeps track whether the contract is paused. When that is true, most actions are blocked + bool public paused = false; + + /// @dev Access modifier for CEO-only functionality + modifier onlyCEO() { + require(msg.sender == ceoAddress); + _; + } + + /// @dev Access modifier for CFO-only functionality + modifier onlyCFO() { + require(msg.sender == cfoAddress); + _; + } + + /// @dev Access modifier for COO-only functionality + modifier onlyCOO() { + require(msg.sender == cooAddress); + _; + } + + modifier onlyCLevel() { + require( + msg.sender == cooAddress || + msg.sender == ceoAddress || + msg.sender == cfoAddress + ); + _; + } + + /// @dev Assigns a new address to act as the CEO. Only available to the current CEO. + /// @param _newCEO The address of the new CEO + function setCEO(address _newCEO) external onlyCEO { + require(_newCEO != address(0)); + + ceoAddress = _newCEO; + } + + /// @dev Assigns a new address to act as the CFO. Only available to the current CEO. + /// @param _newCFO The address of the new CFO + function setCFO(address _newCFO) external onlyCEO { + require(_newCFO != address(0)); + + cfoAddress = _newCFO; + } + + /// @dev Assigns a new address to act as the COO. Only available to the current CEO. + /// @param _newCOO The address of the new COO + function setCOO(address _newCOO) external onlyCEO { + require(_newCOO != address(0)); + + cooAddress = _newCOO; + } + + /*** Pausable functionality adapted from OpenZeppelin ***/ + + /// @dev Modifier to allow actions only when the contract IS NOT paused + modifier whenNotPaused() { + require(!paused); + _; + } + + /// @dev Modifier to allow actions only when the contract IS paused + modifier whenPaused { + require(paused); + _; + } + + /// @dev Called by any "C-level" role to pause the contract. Used only when + /// a bug or exploit is detected and we need to limit damage. + function pause() external onlyCLevel whenNotPaused { + paused = true; + } + + /// @dev Unpauses the smart contract. Can only be called by the CEO, since + /// one reason we may pause the contract is when CFO or COO accounts are + /// compromised. + /// @notice This is public rather than external so it can be called by + /// derived contracts. + function unpause() public onlyCEO whenPaused { + // can't unpause if contract was upgraded + paused = false; + } +} + + + + +/// @title Base contract for CryptoKitties. Holds all common structs, events and base variables. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. +contract KittyBase is KittyAccessControl { + /*** EVENTS ***/ + + /// @dev The Birth event is fired whenever a new kitten comes into existence. This obviously + /// includes any time a cat is created through the giveBirth method, but it is also called + /// when a new gen0 cat is created. + event Birth(address owner, uint256 kittyId, uint256 matronId, uint256 sireId, uint256 genes); + + /// @dev Transfer event as defined in current draft of ERC721. Emitted every time a kitten + /// ownership is assigned, including births. + event Transfer(address from, address to, uint256 tokenId); + + /*** DATA TYPES ***/ + + /// @dev The main Kitty struct. Every cat in CryptoKitties is represented by a copy + /// of this structure, so great care was taken to ensure that it fits neatly into + /// exactly two 256-bit words. Note that the order of the members in this structure + /// is important because of the byte-packing rules used by Ethereum. + /// Ref: http://solidity.readthedocs.io/en/develop/miscellaneous.html + struct Kitty { + // The Kitty's genetic code is packed into these 256-bits, the format is + // sooper-sekret! A cat's genes never change. + uint256 genes; + + // The timestamp from the block when this cat came into existence. + uint64 birthTime; + + // The minimum timestamp after which this cat can engage in breeding + // activities again. This same timestamp is used for the pregnancy + // timer (for matrons) as well as the siring cooldown. + uint64 cooldownEndBlock; + + // The ID of the parents of this kitty, set to 0 for gen0 cats. + // Note that using 32-bit unsigned integers limits us to a "mere" + // 4 billion cats. This number might seem small until you realize + // that Ethereum currently has a limit of about 500 million + // transactions per year! So, this definitely won't be a problem + // for several years (even as Ethereum learns to scale). + uint32 matronId; + uint32 sireId; + + // Set to the ID of the sire cat for matrons that are pregnant, + // zero otherwise. A non-zero value here is how we know a cat + // is pregnant. Used to retrieve the genetic material for the new + // kitten when the birth transpires. + uint32 siringWithId; + + // Set to the index in the cooldown array (see below) that represents + // the current cooldown duration for this Kitty. This starts at zero + // for gen0 cats, and is initialized to floor(generation/2) for others. + // Incremented by one for each successful breeding action, regardless + // of whether this cat is acting as matron or sire. + uint16 cooldownIndex; + + // The "generation number" of this cat. Cats minted by the CK contract + // for sale are called "gen0" and have a generation number of 0. The + // generation number of all other cats is the larger of the two generation + // numbers of their parents, plus one. + // (i.e. max(matron.generation, sire.generation) + 1) + uint16 generation; + } + + /*** CONSTANTS ***/ + + /// @dev A lookup table indicating the cooldown duration after any successful + /// breeding action, called "pregnancy time" for matrons and "siring cooldown" + /// for sires. Designed such that the cooldown roughly doubles each time a cat + /// is bred, encouraging owners not to just keep breeding the same cat over + /// and over again. Caps out at one week (a cat can breed an unbounded number + /// of times, and the maximum cooldown is always seven days). + uint32[14] public cooldowns = [ + uint32(1 minutes), + uint32(2 minutes), + uint32(5 minutes), + uint32(10 minutes), + uint32(30 minutes), + uint32(1 hours), + uint32(2 hours), + uint32(4 hours), + uint32(8 hours), + uint32(16 hours), + uint32(1 days), + uint32(2 days), + uint32(4 days), + uint32(7 days) + ]; + + // An approximation of currently how many seconds are in between blocks. + uint256 public secondsPerBlock = 15; + + /*** STORAGE ***/ + + /// @dev An array containing the Kitty struct for all Kitties in existence. The ID + /// of each cat is actually an index into this array. Note that ID 0 is a negacat, + /// the unKitty, the mythical beast that is the parent of all gen0 cats. A bizarre + /// creature that is both matron and sire... to itself! Has an invalid genetic code. + /// In other words, cat ID 0 is invalid... ;-) + Kitty[] kitties; + + /// @dev A mapping from cat IDs to the address that owns them. All cats have + /// some valid owner address, even gen0 cats are created with a non-zero owner. + mapping (uint256 => address) public kittyIndexToOwner; + + // @dev A mapping from owner address to count of tokens that address owns. + // Used internally inside balanceOf() to resolve ownership count. + mapping (address => uint256) ownershipTokenCount; + + /// @dev A mapping from KittyIDs to an address that has been approved to call + /// transferFrom(). Each Kitty can only have one approved address for transfer + /// at any time. A zero value means no approval is outstanding. + mapping (uint256 => address) public kittyIndexToApproved; + + /// @dev A mapping from KittyIDs to an address that has been approved to use + /// this Kitty for siring via breedWith(). Each Kitty can only have one approved + /// address for siring at any time. A zero value means no approval is outstanding. + mapping (uint256 => address) public sireAllowedToAddress; + + /// @dev The address of the ClockAuction contract that handles sales of Kitties. This + /// same contract handles both peer-to-peer sales as well as the gen0 sales which are + /// initiated every 15 minutes. + SaleClockAuction public saleAuction; + + /// @dev The address of a custom ClockAuction subclassed contract that handles siring + /// auctions. Needs to be separate from saleAuction because the actions taken on success + /// after a sales and siring auction are quite different. + SiringClockAuction public siringAuction; + + /// @dev Assigns ownership of a specific Kitty to an address. + function _transfer(address _from, address _to, uint256 _tokenId) internal { + // Since the number of kittens is capped to 2^32 we can't overflow this + ownershipTokenCount[_to]++; + // transfer ownership + kittyIndexToOwner[_tokenId] = _to; + // When creating new kittens _from is 0x0, but we can't account that address. + if (_from != address(0)) { + ownershipTokenCount[_from]--; + // once the kitten is transferred also clear sire allowances + delete sireAllowedToAddress[_tokenId]; + // clear any previously approved ownership exchange + delete kittyIndexToApproved[_tokenId]; + } + // Emit the transfer event. + Transfer(_from, _to, _tokenId); + } + + /// @dev An internal method that creates a new kitty and stores it. This + /// method doesn't do any checking and should only be called when the + /// input data is known to be valid. Will generate both a Birth event + /// and a Transfer event. + /// @param _matronId The kitty ID of the matron of this cat (zero for gen0) + /// @param _sireId The kitty ID of the sire of this cat (zero for gen0) + /// @param _generation The generation number of this cat, must be computed by caller. + /// @param _genes The kitty's genetic code. + /// @param _owner The inital owner of this cat, must be non-zero (except for the unKitty, ID 0) + function _createKitty( + uint256 _matronId, + uint256 _sireId, + uint256 _generation, + uint256 _genes, + address _owner + ) + internal + returns (uint) + { + // These requires are not strictly necessary, our calling code should make + // sure that these conditions are never broken. However! _createKitty() is already + // an expensive call (for storage), and it doesn't hurt to be especially careful + // to ensure our data structures are always valid. + require(_matronId == uint256(uint32(_matronId))); + require(_sireId == uint256(uint32(_sireId))); + require(_generation == uint256(uint16(_generation))); + + // New kitty starts with the same cooldown as parent gen/2 + uint16 cooldownIndex = uint16(_generation / 2); + if (cooldownIndex > 13) { + cooldownIndex = 13; + } + + Kitty memory _kitty = Kitty({ + genes: _genes, + birthTime: uint64(now), + cooldownEndBlock: 0, + matronId: uint32(_matronId), + sireId: uint32(_sireId), + siringWithId: 0, + cooldownIndex: cooldownIndex, + generation: uint16(_generation) + }); + uint256 newKittenId = kitties.push(_kitty) - 1; + + // It's probably never going to happen, 4 billion cats is A LOT, but + // let's just be 100% sure we never let this happen. + require(newKittenId == uint256(uint32(newKittenId))); + + // emit the birth event + Birth( + _owner, + newKittenId, + uint256(_kitty.matronId), + uint256(_kitty.sireId), + _kitty.genes + ); + + // This will assign ownership, and also emit the Transfer event as + // per ERC721 draft + _transfer(0, _owner, newKittenId); + + return newKittenId; + } + + // Any C-level can fix how many seconds per blocks are currently observed. + function setSecondsPerBlock(uint256 secs) external onlyCLevel { + require(secs < cooldowns[0]); + secondsPerBlock = secs; + } +} + + + + + +/// @title The external contract that is responsible for generating metadata for the kitties, +/// it has one function that will return the data as bytes. +contract ERC721Metadata { + /// @dev Given a token Id, returns a byte array that is supposed to be converted into string. + function getMetadata(uint256 _tokenId, string) public view returns (bytes32[4] buffer, uint256 count) { + if (_tokenId == 1) { + buffer[0] = "Hello World! :D"; + count = 15; + } else if (_tokenId == 2) { + buffer[0] = "I would definitely choose a medi"; + buffer[1] = "um length string."; + count = 49; + } else if (_tokenId == 3) { + buffer[0] = "Lorem ipsum dolor sit amet, mi e"; + buffer[1] = "st accumsan dapibus augue lorem,"; + buffer[2] = " tristique vestibulum id, libero"; + buffer[3] = " suscipit varius sapien aliquam."; + count = 128; + } + } +} + + +/// @title The facet of the CryptoKitties core contract that manages ownership, ERC-721 (draft) compliant. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev Ref: https://github.com/ethereum/EIPs/issues/721 +/// See the KittyCore contract documentation to understand how the various contract facets are arranged. +contract KittyOwnership is KittyBase, ERC721 { + + /// @notice Name and symbol of the non fungible token, as defined in ERC721. + string public constant name = "CryptoKitties"; + string public constant symbol = "CK"; + + // The contract that will return kitty metadata + ERC721Metadata public erc721Metadata; + + bytes4 constant InterfaceSignature_ERC165 = + bytes4(keccak256('supportsInterface(bytes4)')); + + bytes4 constant InterfaceSignature_ERC721 = + bytes4(keccak256('name()')) ^ + bytes4(keccak256('symbol()')) ^ + bytes4(keccak256('totalSupply()')) ^ + bytes4(keccak256('balanceOf(address)')) ^ + bytes4(keccak256('ownerOf(uint256)')) ^ + bytes4(keccak256('approve(address,uint256)')) ^ + bytes4(keccak256('transfer(address,uint256)')) ^ + bytes4(keccak256('transferFrom(address,address,uint256)')) ^ + bytes4(keccak256('tokensOfOwner(address)')) ^ + bytes4(keccak256('tokenMetadata(uint256,string)')); + + /// @notice Introspection interface as per ERC-165 (https://github.com/ethereum/EIPs/issues/165). + /// Returns true for any standardized interfaces implemented by this contract. We implement + /// ERC-165 (obviously!) and ERC-721. + function supportsInterface(bytes4 _interfaceID) external view returns (bool) + { + // DEBUG ONLY + //require((InterfaceSignature_ERC165 == 0x01ffc9a7) && (InterfaceSignature_ERC721 == 0x9a20483d)); + + return ((_interfaceID == InterfaceSignature_ERC165) || (_interfaceID == InterfaceSignature_ERC721)); + } + + /// @dev Set the address of the sibling contract that tracks metadata. + /// CEO only. + function setMetadataAddress(address _contractAddress) public onlyCEO { + erc721Metadata = ERC721Metadata(_contractAddress); + } + + // Internal utility functions: These functions all assume that their input arguments + // are valid. We leave it to public methods to sanitize their inputs and follow + // the required logic. + + /// @dev Checks if a given address is the current owner of a particular Kitty. + /// @param _claimant the address we are validating against. + /// @param _tokenId kitten id, only valid when > 0 + function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { + return kittyIndexToOwner[_tokenId] == _claimant; + } + + /// @dev Checks if a given address currently has transferApproval for a particular Kitty. + /// @param _claimant the address we are confirming kitten is approved for. + /// @param _tokenId kitten id, only valid when > 0 + function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) { + return kittyIndexToApproved[_tokenId] == _claimant; + } + + /// @dev Marks an address as being approved for transferFrom(), overwriting any previous + /// approval. Setting _approved to address(0) clears all transfer approval. + /// NOTE: _approve() does NOT send the Approval event. This is intentional because + /// _approve() and transferFrom() are used together for putting Kitties on auction, and + /// there is no value in spamming the log with Approval events in that case. + function _approve(uint256 _tokenId, address _approved) internal { + kittyIndexToApproved[_tokenId] = _approved; + } + + /// @notice Returns the number of Kitties owned by a specific address. + /// @param _owner The owner address to check. + /// @dev Required for ERC-721 compliance + function balanceOf(address _owner) public view returns (uint256 count) { + return ownershipTokenCount[_owner]; + } + + /// @notice Transfers a Kitty to another address. If transferring to a smart + /// contract be VERY CAREFUL to ensure that it is aware of ERC-721 (or + /// CryptoKitties specifically) or your Kitty may be lost forever. Seriously. + /// @param _to The address of the recipient, can be a user or contract. + /// @param _tokenId The ID of the Kitty to transfer. + /// @dev Required for ERC-721 compliance. + function transfer( + address _to, + uint256 _tokenId + ) + external + whenNotPaused + { + // Safety check to prevent against an unexpected 0x0 default. + require(_to != address(0)); + // Disallow transfers to this contract to prevent accidental misuse. + // The contract should never own any kitties (except very briefly + // after a gen0 cat is created and before it goes on auction). + require(_to != address(this)); + // Disallow transfers to the auction contracts to prevent accidental + // misuse. Auction contracts should only take ownership of kitties + // through the allow + transferFrom flow. + require(_to != address(saleAuction)); + require(_to != address(siringAuction)); + + // You can only send your own cat. + require(_owns(msg.sender, _tokenId)); + + // Reassign ownership, clear pending approvals, emit Transfer event. + _transfer(msg.sender, _to, _tokenId); + } + + /// @notice Grant another address the right to transfer a specific Kitty via + /// transferFrom(). This is the preferred flow for transfering NFTs to contracts. + /// @param _to The address to be granted transfer approval. Pass address(0) to + /// clear all approvals. + /// @param _tokenId The ID of the Kitty that can be transferred if this call succeeds. + /// @dev Required for ERC-721 compliance. + function approve( + address _to, + uint256 _tokenId + ) + external + whenNotPaused + { + // Only an owner can grant transfer approval. + require(_owns(msg.sender, _tokenId)); + + // Register the approval (replacing any previous approval). + _approve(_tokenId, _to); + + // Emit approval event. + Approval(msg.sender, _to, _tokenId); + } + + /// @notice Transfer a Kitty owned by another address, for which the calling address + /// has previously been granted transfer approval by the owner. + /// @param _from The address that owns the Kitty to be transfered. + /// @param _to The address that should take ownership of the Kitty. Can be any address, + /// including the caller. + /// @param _tokenId The ID of the Kitty to be transferred. + /// @dev Required for ERC-721 compliance. + function transferFrom( + address _from, + address _to, + uint256 _tokenId + ) + external + whenNotPaused + { + // Safety check to prevent against an unexpected 0x0 default. + require(_to != address(0)); + // Disallow transfers to this contract to prevent accidental misuse. + // The contract should never own any kitties (except very briefly + // after a gen0 cat is created and before it goes on auction). + require(_to != address(this)); + // Check for approval and valid ownership + require(_approvedFor(msg.sender, _tokenId)); + require(_owns(_from, _tokenId)); + + // Reassign ownership (also clears pending approvals and emits Transfer event). + _transfer(_from, _to, _tokenId); + } + + /// @notice Returns the total number of Kitties currently in existence. + /// @dev Required for ERC-721 compliance. + function totalSupply() public view returns (uint) { + return kitties.length - 1; + } + + /// @notice Returns the address currently assigned ownership of a given Kitty. + /// @dev Required for ERC-721 compliance. + function ownerOf(uint256 _tokenId) + external + view + returns (address owner) + { + owner = kittyIndexToOwner[_tokenId]; + + require(owner != address(0)); + } + + /// @notice Returns a list of all Kitty IDs assigned to an address. + /// @param _owner The owner whose Kitties we are interested in. + /// @dev This method MUST NEVER be called by smart contract code. First, it's fairly + /// expensive (it walks the entire Kitty array looking for cats belonging to owner), + /// but it also returns a dynamic array, which is only supported for web3 calls, and + /// not contract-to-contract calls. + function tokensOfOwner(address _owner) external view returns(uint256[] ownerTokens) { + uint256 tokenCount = balanceOf(_owner); + + if (tokenCount == 0) { + // Return an empty array + return new uint256[](0); + } else { + uint256[] memory result = new uint256[](tokenCount); + uint256 totalCats = totalSupply(); + uint256 resultIndex = 0; + + // We count on the fact that all cats have IDs starting at 1 and increasing + // sequentially up to the totalCat count. + uint256 catId; + + for (catId = 1; catId <= totalCats; catId++) { + if (kittyIndexToOwner[catId] == _owner) { + result[resultIndex] = catId; + resultIndex++; + } + } + + return result; + } + } + + /// @dev Adapted from memcpy() by @arachnid (Nick Johnson ) + /// This method is licenced under the Apache License. + /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol + function _memcpy(uint _dest, uint _src, uint _len) private view { + // Copy word-length chunks while possible + for(; _len >= 32; _len -= 32) { + assembly { + mstore(_dest, mload(_src)) + } + _dest += 32; + _src += 32; + } + + // Copy remaining bytes + uint256 mask = 256 ** (32 - _len) - 1; + assembly { + let srcpart := and(mload(_src), not(mask)) + let destpart := and(mload(_dest), mask) + mstore(_dest, or(destpart, srcpart)) + } + } + + /// @dev Adapted from toString(slice) by @arachnid (Nick Johnson ) + /// This method is licenced under the Apache License. + /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol + function _toString(bytes32[4] _rawBytes, uint256 _stringLength) private view returns (string) { + var outputString = new string(_stringLength); + uint256 outputPtr; + uint256 bytesPtr; + + assembly { + outputPtr := add(outputString, 32) + bytesPtr := _rawBytes + } + + _memcpy(outputPtr, bytesPtr, _stringLength); + + return outputString; + } + + /// @notice Returns a URI pointing to a metadata package for this token conforming to + /// ERC-721 (https://github.com/ethereum/EIPs/issues/721) + /// @param _tokenId The ID number of the Kitty whose metadata should be returned. + function tokenMetadata(uint256 _tokenId, string _preferredTransport) external view returns (string infoUrl) { + require(erc721Metadata != address(0)); + bytes32[4] memory buffer; + uint256 count; + (buffer, count) = erc721Metadata.getMetadata(_tokenId, _preferredTransport); + + return _toString(buffer, count); + } +} + + + +/// @title A facet of KittyCore that manages Kitty siring, gestation, and birth. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. +contract KittyBreeding is KittyOwnership { + + /// @dev The Pregnant event is fired when two cats successfully breed and the pregnancy + /// timer begins for the matron. + event Pregnant(address owner, uint256 matronId, uint256 sireId, uint256 cooldownEndBlock); + + /// @notice The minimum payment required to use breedWithAuto(). This fee goes towards + /// the gas cost paid by whatever calls giveBirth(), and can be dynamically updated by + /// the COO role as the gas price changes. + uint256 public autoBirthFee = 2 finny; + + // Keeps track of number of pregnant kitties. + uint256 public pregnantKitties; + + /// @dev The address of the sibling contract that is used to implement the sooper-sekret + /// genetic combination algorithm. + GeneScienceInterface public geneScience; + + /// @dev Update the address of the genetic contract, can only be called by the CEO. + /// @param _address An address of a GeneScience contract instance to be used from this point forward. + function setGeneScienceAddress(address _address) external onlyCEO { + GeneScienceInterface candidateContract = GeneScienceInterface(_address); + + // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 + require(candidateContract.isGeneScience()); + + // Set the new contract address + geneScience = candidateContract; + } + + /// @dev Checks that a given kitten is able to breed. Requires that the + /// current cooldown is finished (for sires) and also checks that there is + /// no pending pregnancy. + function _isReadyToBreed(Kitty _kit) internal view returns (bool) { + // In addition to checking the cooldownEndBlock, we also need to check to see if + // the cat has a pending birth; there can be some period of time between the end + // of the pregnacy timer and the birth event. + return (_kit.siringWithId == 0) && (_kit.cooldownEndBlock <= uint64(block.number)); + } + + /// @dev Check if a sire has authorized breeding with this matron. True if both sire + /// and matron have the same owner, or if the sire has given siring permission to + /// the matron's owner (via approveSiring()). + function _isSiringPermitted(uint256 _sireId, uint256 _matronId) internal view returns (bool) { + address matronOwner = kittyIndexToOwner[_matronId]; + address sireOwner = kittyIndexToOwner[_sireId]; + + // Siring is okay if they have same owner, or if the matron's owner was given + // permission to breed with this sire. + return (matronOwner == sireOwner || sireAllowedToAddress[_sireId] == matronOwner); + } + + /// @dev Set the cooldownEndTime for the given Kitty, based on its current cooldownIndex. + /// Also increments the cooldownIndex (unless it has hit the cap). + /// @param _kitten A reference to the Kitty in storage which needs its timer started. + function _triggerCooldown(Kitty storage _kitten) internal { + // Compute an estimation of the cooldown time in blocks (based on current cooldownIndex). + _kitten.cooldownEndBlock = uint64((cooldowns[_kitten.cooldownIndex]/secondsPerBlock) + block.number); + + // Increment the breeding count, clamping it at 13, which is the length of the + // cooldowns array. We could check the array size dynamically, but hard-coding + // this as a constant saves gas. Yay, Solidity! + if (_kitten.cooldownIndex < 13) { + _kitten.cooldownIndex += 1; + } + } + + /// @notice Grants approval to another user to sire with one of your Kitties. + /// @param _addr The address that will be able to sire with your Kitty. Set to + /// address(0) to clear all siring approvals for this Kitty. + /// @param _sireId A Kitty that you own that _addr will now be able to sire with. + function approveSiring(address _addr, uint256 _sireId) + external + whenNotPaused + { + require(_owns(msg.sender, _sireId)); + sireAllowedToAddress[_sireId] = _addr; + } + + /// @dev Updates the minimum payment required for calling giveBirthAuto(). Can only + /// be called by the COO address. (This fee is used to offset the gas cost incurred + /// by the autobirth daemon). + function setAutoBirthFee(uint256 val) external onlyCOO { + autoBirthFee = val; + } + + /// @dev Checks to see if a given Kitty is pregnant and (if so) if the gestation + /// period has passed. + function _isReadyToGiveBirth(Kitty _matron) private view returns (bool) { + return (_matron.siringWithId != 0) && (_matron.cooldownEndBlock <= uint64(block.number)); + } + + /// @notice Checks that a given kitten is able to breed (i.e. it is not pregnant or + /// in the middle of a siring cooldown). + /// @param _kittyId reference the id of the kitten, any user can inquire about it + function isReadyToBreed(uint256 _kittyId) + public + view + returns (bool) + { + require(_kittyId > 0); + Kitty storage kit = kitties[_kittyId]; + return _isReadyToBreed(kit); + } + + /// @dev Checks whether a kitty is currently pregnant. + /// @param _kittyId reference the id of the kitten, any user can inquire about it + function isPregnant(uint256 _kittyId) + public + view + returns (bool) + { + require(_kittyId > 0); + // A kitty is pregnant if and only if this field is set + return kitties[_kittyId].siringWithId != 0; + } + + /// @dev Internal check to see if a given sire and matron are a valid mating pair. DOES NOT + /// check ownership permissions (that is up to the caller). + /// @param _matron A reference to the Kitty struct of the potential matron. + /// @param _matronId The matron's ID. + /// @param _sire A reference to the Kitty struct of the potential sire. + /// @param _sireId The sire's ID + function _isValidMatingPair( + Kitty storage _matron, + uint256 _matronId, + Kitty storage _sire, + uint256 _sireId + ) + private + view + returns(bool) + { + // A Kitty can't breed with itself! + if (_matronId == _sireId) { + return false; + } + + // Kitties can't breed with their parents. + if (_matron.matronId == _sireId || _matron.sireId == _sireId) { + return false; + } + if (_sire.matronId == _matronId || _sire.sireId == _matronId) { + return false; + } + + // We can short circuit the sibling check (below) if either cat is + // gen zero (has a matron ID of zero). + if (_sire.matronId == 0 || _matron.matronId == 0) { + return true; + } + + // Kitties can't breed with full or half siblings. + if (_sire.matronId == _matron.matronId || _sire.matronId == _matron.sireId) { + return false; + } + if (_sire.sireId == _matron.matronId || _sire.sireId == _matron.sireId) { + return false; + } + + // Everything seems cool! Let's get DTF. + return true; + } + + /// @dev Internal check to see if a given sire and matron are a valid mating pair for + /// breeding via auction (i.e. skips ownership and siring approval checks). + function _canBreedWithViaAuction(uint256 _matronId, uint256 _sireId) + internal + view + returns (bool) + { + Kitty storage matron = kitties[_matronId]; + Kitty storage sire = kitties[_sireId]; + return _isValidMatingPair(matron, _matronId, sire, _sireId); + } + + /// @notice Checks to see if two cats can breed together, including checks for + /// ownership and siring approvals. Does NOT check that both cats are ready for + /// breeding (i.e. breedWith could still fail until the cooldowns are finished). + /// TODO: Shouldn't this check pregnancy and cooldowns?!? + /// @param _matronId The ID of the proposed matron. + /// @param _sireId The ID of the proposed sire. + function canBreedWith(uint256 _matronId, uint256 _sireId) + external + view + returns(bool) + { + require(_matronId > 0); + require(_sireId > 0); + Kitty storage matron = kitties[_matronId]; + Kitty storage sire = kitties[_sireId]; + return _isValidMatingPair(matron, _matronId, sire, _sireId) && + _isSiringPermitted(_sireId, _matronId); + } + + /// @dev Internal utility function to initiate breeding, assumes that all breeding + /// requirements have been checked. + function _breedWith(uint256 _matronId, uint256 _sireId) internal { + // Grab a reference to the Kitties from storage. + Kitty storage sire = kitties[_sireId]; + Kitty storage matron = kitties[_matronId]; + + // Mark the matron as pregnant, keeping track of who the sire is. + matron.siringWithId = uint32(_sireId); + + // Trigger the cooldown for both parents. + _triggerCooldown(sire); + _triggerCooldown(matron); + + // Clear siring permission for both parents. This may not be strictly necessary + // but it's likely to avoid confusion! + delete sireAllowedToAddress[_matronId]; + delete sireAllowedToAddress[_sireId]; + + // Every time a kitty gets pregnant, counter is incremented. + pregnantKitties++; + + // Emit the pregnancy event. + Pregnant(kittyIndexToOwner[_matronId], _matronId, _sireId, matron.cooldownEndBlock); + } + + /// @notice Breed a Kitty you own (as matron) with a sire that you own, or for which you + /// have previously been given Siring approval. Will either make your cat pregnant, or will + /// fail entirely. Requires a pre-payment of the fee given out to the first caller of giveBirth() + /// @param _matronId The ID of the Kitty acting as matron (will end up pregnant if successful) + /// @param _sireId The ID of the Kitty acting as sire (will begin its siring cooldown if successful) + function breedWithAuto(uint256 _matronId, uint256 _sireId) + external + payable + whenNotPaused + { + // Checks for payment. + require(msg.value >= autoBirthFee); + + // Caller must own the matron. + require(_owns(msg.sender, _matronId)); + + // Neither sire nor matron are allowed to be on auction during a normal + // breeding operation, but we don't need to check that explicitly. + // For matron: The caller of this function can't be the owner of the matron + // because the owner of a Kitty on auction is the auction house, and the + // auction house will never call breedWith(). + // For sire: Similarly, a sire on auction will be owned by the auction house + // and the act of transferring ownership will have cleared any oustanding + // siring approval. + // Thus we don't need to spend gas explicitly checking to see if either cat + // is on auction. + + // Check that matron and sire are both owned by caller, or that the sire + // has given siring permission to caller (i.e. matron's owner). + // Will fail for _sireId = 0 + require(_isSiringPermitted(_sireId, _matronId)); + + // Grab a reference to the potential matron + Kitty storage matron = kitties[_matronId]; + + // Make sure matron isn't pregnant, or in the middle of a siring cooldown + require(_isReadyToBreed(matron)); + + // Grab a reference to the potential sire + Kitty storage sire = kitties[_sireId]; + + // Make sure sire isn't pregnant, or in the middle of a siring cooldown + require(_isReadyToBreed(sire)); + + // Test that these cats are a valid mating pair. + require(_isValidMatingPair( + matron, + _matronId, + sire, + _sireId + )); + + // All checks passed, kitty gets pregnant! + _breedWith(_matronId, _sireId); + } + + /// @notice Have a pregnant Kitty give birth! + /// @param _matronId A Kitty ready to give birth. + /// @return The Kitty ID of the new kitten. + /// @dev Looks at a given Kitty and, if pregnant and if the gestation period has passed, + /// combines the genes of the two parents to create a new kitten. The new Kitty is assigned + /// to the current owner of the matron. Upon successful completion, both the matron and the + /// new kitten will be ready to breed again. Note that anyone can call this function (if they + /// are willing to pay the gas!), but the new kitten always goes to the mother's owner. + function giveBirth(uint256 _matronId) + external + whenNotPaused + returns(uint256) + { + // Grab a reference to the matron in storage. + Kitty storage matron = kitties[_matronId]; + + // Check that the matron is a valid cat. + require(matron.birthTime != 0); + + // Check that the matron is pregnant, and that its time has come! + require(_isReadyToGiveBirth(matron)); + + // Grab a reference to the sire in storage. + uint256 sireId = matron.siringWithId; + Kitty storage sire = kitties[sireId]; + + // Determine the higher generation number of the two parents + uint16 parentGen = matron.generation; + if (sire.generation > matron.generation) { + parentGen = sire.generation; + } + + // Call the sooper-sekret gene mixing operation. + uint256 childGenes = geneScience.mixGenes(matron.genes, sire.genes, matron.cooldownEndBlock - 1); + + // Make the new kitten! + address owner = kittyIndexToOwner[_matronId]; + uint256 kittenId = _createKitty(_matronId, matron.siringWithId, parentGen + 1, childGenes, owner); + + // Clear the reference to sire from the matron (REQUIRED! Having siringWithId + // set is what marks a matron as being pregnant.) + delete matron.siringWithId; + + // Every time a kitty gives birth counter is decremented. + pregnantKitties--; + + // Send the balance fee to the person who made birth happen. + msg.sender.send(autoBirthFee); + + // return the new kitten's ID + return kittenId; + } +} + + + + + + + + + + +/// @title Auction Core +/// @dev Contains models, variables, and internal methods for the auction. +/// @notice We omit a fallback function to prevent accidental sends to this contract. +contract ClockAuctionBase { + + // Represents an auction on an NFT + struct Auction { + // Current owner of NFT + address seller; + // Price (in wei) at beginning of auction + uint128 startingPrice; + // Price (in wei) at end of auction + uint128 endingPrice; + // Duration (in seconds) of auction + uint64 duration; + // Time when auction started + // NOTE: 0 if this auction has been concluded + uint64 startedAt; + } + + // Reference to contract tracking NFT ownership + ERC721 public nonFungibleContract; + + // Cut owner takes on each auction, measured in basis points (1/100 of a percent). + // Values 0-10,000 map to 0%-100% + uint256 public ownerCut; + + // Map from token ID to their corresponding auction. + mapping (uint256 => Auction) tokenIdToAuction; + + event AuctionCreated(uint256 tokenId, uint256 startingPrice, uint256 endingPrice, uint256 duration); + event AuctionSuccessful(uint256 tokenId, uint256 totalPrice, address winner); + event AuctionCancelled(uint256 tokenId); + + /// @dev Returns true if the claimant owns the token. + /// @param _claimant - Address claiming to own the token. + /// @param _tokenId - ID of token whose ownership to verify. + function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { + return (nonFungibleContract.ownerOf(_tokenId) == _claimant); + } + + /// @dev Escrows the NFT, assigning ownership to this contract. + /// Throws if the escrow fails. + /// @param _owner - Current owner address of token to escrow. + /// @param _tokenId - ID of token whose approval to verify. + function _escrow(address _owner, uint256 _tokenId) internal { + // it will throw if transfer fails + nonFungibleContract.transferFrom(_owner, this, _tokenId); + } + + /// @dev Transfers an NFT owned by this contract to another address. + /// Returns true if the transfer succeeds. + /// @param _receiver - Address to transfer NFT to. + /// @param _tokenId - ID of token to transfer. + function _transfer(address _receiver, uint256 _tokenId) internal { + // it will throw if transfer fails + nonFungibleContract.transfer(_receiver, _tokenId); + } + + /// @dev Adds an auction to the list of open auctions. Also fires the + /// AuctionCreated event. + /// @param _tokenId The ID of the token to be put on auction. + /// @param _auction Auction to add. + function _addAuction(uint256 _tokenId, Auction _auction) internal { + // Require that all auctions have a duration of + // at least one minute. (Keeps our math from getting hairy!) + require(_auction.duration >= 1 minutes); + + tokenIdToAuction[_tokenId] = _auction; + + AuctionCreated( + uint256(_tokenId), + uint256(_auction.startingPrice), + uint256(_auction.endingPrice), + uint256(_auction.duration) + ); + } + + /// @dev Cancels an auction unconditionally. + function _cancelAuction(uint256 _tokenId, address _seller) internal { + _removeAuction(_tokenId); + _transfer(_seller, _tokenId); + AuctionCancelled(_tokenId); + } + + /// @dev Computes the price and transfers winnings. + /// Does NOT transfer ownership of token. + function _bid(uint256 _tokenId, uint256 _bidAmount) + internal + returns (uint256) + { + // Get a reference to the auction struct + Auction storage auction = tokenIdToAuction[_tokenId]; + + // Explicitly check that this auction is currently live. + // (Because of how Ethereum mappings work, we can't just count + // on the lookup above failing. An invalid _tokenId will just + // return an auction object that is all zeros.) + require(_isOnAuction(auction)); + + // Check that the bid is greater than or equal to the current price + uint256 price = _currentPrice(auction); + require(_bidAmount >= price); + + // Grab a reference to the seller before the auction struct + // gets deleted. + address seller = auction.seller; + + // The bid is good! Remove the auction before sending the fees + // to the sender so we can't have a reentrancy attack. + _removeAuction(_tokenId); + + // Transfer proceeds to seller (if there are any!) + if (price > 0) { + // Calculate the auctioneer's cut. + // (NOTE: _computeCut() is guaranteed to return a + // value <= price, so this subtraction can't go negative.) + uint256 auctioneerCut = _computeCut(price); + uint256 sellerProceeds = price - auctioneerCut; + + // NOTE: Doing a transfer() in the middle of a complex + // method like this is generally discouraged because of + // reentrancy attacks and DoS attacks if the seller is + // a contract with an invalid fallback function. We explicitly + // guard against reentrancy attacks by removing the auction + // before calling transfer(), and the only thing the seller + // can DoS is the sale of their own asset! (And if it's an + // accident, they can call cancelAuction(). ) + seller.transfer(sellerProceeds); + } + + // Calculate any excess funds included with the bid. If the excess + // is anything worth worrying about, transfer it back to bidder. + // NOTE: We checked above that the bid amount is greater than or + // equal to the price so this cannot underflow. + uint256 bidExcess = _bidAmount - price; + + // Return the funds. Similar to the previous transfer, this is + // not susceptible to a re-entry attack because the auction is + // removed before any transfers occur. + msg.sender.transfer(bidExcess); + + // Tell the world! + AuctionSuccessful(_tokenId, price, msg.sender); + + return price; + } + + /// @dev Removes an auction from the list of open auctions. + /// @param _tokenId - ID of NFT on auction. + function _removeAuction(uint256 _tokenId) internal { + delete tokenIdToAuction[_tokenId]; + } + + /// @dev Returns true if the NFT is on auction. + /// @param _auction - Auction to check. + function _isOnAuction(Auction storage _auction) internal view returns (bool) { + return (_auction.startedAt > 0); + } + + /// @dev Returns current price of an NFT on auction. Broken into two + /// functions (this one, that computes the duration from the auction + /// structure, and the other that does the price computation) so we + /// can easily test that the price computation works correctly. + function _currentPrice(Auction storage _auction) + internal + view + returns (uint256) + { + uint256 secondsPassed = 0; + + // A bit of insurance against negative values (or wraparound). + // Probably not necessary (since Ethereum guarnatees that the + // now variable doesn't ever go backwards). + if (now > _auction.startedAt) { + secondsPassed = now - _auction.startedAt; + } + + return _computeCurrentPrice( + _auction.startingPrice, + _auction.endingPrice, + _auction.duration, + secondsPassed + ); + } + + /// @dev Computes the current price of an auction. Factored out + /// from _currentPrice so we can run extensive unit tests. + /// When testing, make this function public and turn on + /// `Current price computation` test suite. + function _computeCurrentPrice( + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration, + uint256 _secondsPassed + ) + internal + pure + returns (uint256) + { + // NOTE: We don't use SafeMath (or similar) in this function because + // all of our public functions carefully cap the maximum values for + // time (at 64-bits) and currency (at 128-bits). _duration is + // also known to be non-zero (see the require() statement in + // _addAuction()) + if (_secondsPassed >= _duration) { + // We've reached the end of the dynamic pricing portion + // of the auction, just return the end price. + return _endingPrice; + } else { + // Starting price can be higher than ending price (and often is!), so + // this delta can be negative. + int256 totalPriceChange = int256(_endingPrice) - int256(_startingPrice); + + // This multiplication can't overflow, _secondsPassed will easily fit within + // 64-bits, and totalPriceChange will easily fit within 128-bits, their product + // will always fit within 256-bits. + int256 currentPriceChange = totalPriceChange * int256(_secondsPassed) / int256(_duration); + + // currentPriceChange can be negative, but if so, will have a magnitude + // less that _startingPrice. Thus, this result will always end up positive. + int256 currentPrice = int256(_startingPrice) + currentPriceChange; + + return uint256(currentPrice); + } + } + + /// @dev Computes owner's cut of a sale. + /// @param _price - Sale price of NFT. + function _computeCut(uint256 _price) internal view returns (uint256) { + // NOTE: We don't use SafeMath (or similar) in this function because + // all of our entry functions carefully cap the maximum values for + // currency (at 128-bits), and ownerCut <= 10000 (see the require() + // statement in the ClockAuction constructor). The result of this + // function is always guaranteed to be <= _price. + return _price * ownerCut / 10000; + } + +} + + + + + + + +/** + * @title Pausable + * @dev Base contract which allows children to implement an emergency stop mechanism. + */ +contract Pausable is Ownable { + event Pause(); + event Unpause(); + + bool public paused = false; + + + /** + * @dev modifier to allow actions only when the contract IS paused + */ + modifier whenNotPaused() { + require(!paused); + _; + } + + /** + * @dev modifier to allow actions only when the contract IS NOT paused + */ + modifier whenPaused { + require(paused); + _; + } + + /** + * @dev called by the owner to pause, triggers stopped state + */ + function pause() onlyOwner whenNotPaused returns (bool) { + paused = true; + Pause(); + return true; + } + + /** + * @dev called by the owner to unpause, returns to normal state + */ + function unpause() onlyOwner whenPaused returns (bool) { + paused = false; + Unpause(); + return true; + } +} + + +/// @title Clock auction for non-fungible tokens. +/// @notice We omit a fallback function to prevent accidental sends to this contract. +contract ClockAuction is Pausable, ClockAuctionBase { + + /// @dev The ERC-165 interface signature for ERC-721. + /// Ref: https://github.com/ethereum/EIPs/issues/165 + /// Ref: https://github.com/ethereum/EIPs/issues/721 + bytes4 constant InterfaceSignature_ERC721 = bytes4(0x9a20483d); + + /// @dev Constructor creates a reference to the NFT ownership contract + /// and verifies the owner cut is in the valid range. + /// @param _nftAddress - address of a deployed contract implementing + /// the Nonfungible Interface. + /// @param _cut - percent cut the owner takes on each auction, must be + /// between 0-10,000. + function ClockAuction(address _nftAddress, uint256 _cut) public { + require(_cut <= 10000); + ownerCut = _cut; + + ERC721 candidateContract = ERC721(_nftAddress); + require(candidateContract.supportsInterface(InterfaceSignature_ERC721)); + nonFungibleContract = candidateContract; + } + + /// @dev Remove all Ether from the contract, which is the owner's cuts + /// as well as any Ether sent directly to the contract address. + /// Always transfers to the NFT contract, but can be called either by + /// the owner or the NFT contract. + function withdrawBalance() external { + address nftAddress = address(nonFungibleContract); + + require( + msg.sender == owner || + msg.sender == nftAddress + ); + // We are using this boolean method to make sure that even if one fails it will still work + bool res = nftAddress.send(this.balance); + } + + /// @dev Creates and begins a new auction. + /// @param _tokenId - ID of token to auction, sender must be owner. + /// @param _startingPrice - Price of item (in wei) at beginning of auction. + /// @param _endingPrice - Price of item (in wei) at end of auction. + /// @param _duration - Length of time to move between starting + /// price and ending price (in seconds). + /// @param _seller - Seller, if not the message sender + function createAuction( + uint256 _tokenId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration, + address _seller + ) + external + whenNotPaused + { + // Sanity check that no inputs overflow how many bits we've allocated + // to store them in the auction struct. + require(_startingPrice == uint256(uint128(_startingPrice))); + require(_endingPrice == uint256(uint128(_endingPrice))); + require(_duration == uint256(uint64(_duration))); + + require(_owns(msg.sender, _tokenId)); + _escrow(msg.sender, _tokenId); + Auction memory auction = Auction( + _seller, + uint128(_startingPrice), + uint128(_endingPrice), + uint64(_duration), + uint64(now) + ); + _addAuction(_tokenId, auction); + } + + /// @dev Bids on an open auction, completing the auction and transferring + /// ownership of the NFT if enough Ether is supplied. + /// @param _tokenId - ID of token to bid on. + function bid(uint256 _tokenId) + external + payable + whenNotPaused + { + // _bid will throw if the bid or funds transfer fails + _bid(_tokenId, msg.value); + _transfer(msg.sender, _tokenId); + } + + /// @dev Cancels an auction that hasn't been won yet. + /// Returns the NFT to original owner. + /// @notice This is a state-modifying function that can + /// be called while the contract is paused. + /// @param _tokenId - ID of token on auction + function cancelAuction(uint256 _tokenId) + external + { + Auction storage auction = tokenIdToAuction[_tokenId]; + require(_isOnAuction(auction)); + address seller = auction.seller; + require(msg.sender == seller); + _cancelAuction(_tokenId, seller); + } + + /// @dev Cancels an auction when the contract is paused. + /// Only the owner may do this, and NFTs are returned to + /// the seller. This should only be used in emergencies. + /// @param _tokenId - ID of the NFT on auction to cancel. + function cancelAuctionWhenPaused(uint256 _tokenId) + whenPaused + onlyOwner + external + { + Auction storage auction = tokenIdToAuction[_tokenId]; + require(_isOnAuction(auction)); + _cancelAuction(_tokenId, auction.seller); + } + + /// @dev Returns auction info for an NFT on auction. + /// @param _tokenId - ID of NFT on auction. + function getAuction(uint256 _tokenId) + external + view + returns + ( + address seller, + uint256 startingPrice, + uint256 endingPrice, + uint256 duration, + uint256 startedAt + ) { + Auction storage auction = tokenIdToAuction[_tokenId]; + require(_isOnAuction(auction)); + return ( + auction.seller, + auction.startingPrice, + auction.endingPrice, + auction.duration, + auction.startedAt + ); + } + + /// @dev Returns the current price of an auction. + /// @param _tokenId - ID of the token price we are checking. + function getCurrentPrice(uint256 _tokenId) + external + view + returns (uint256) + { + Auction storage auction = tokenIdToAuction[_tokenId]; + require(_isOnAuction(auction)); + return _currentPrice(auction); + } + +} + + +/// @title Reverse auction modified for siring +/// @notice We omit a fallback function to prevent accidental sends to this contract. +contract SiringClockAuction is ClockAuction { + + // @dev Sanity check that allows us to ensure that we are pointing to the + // right auction in our setSiringAuctionAddress() call. + bool public isSiringClockAuction = true; + + // Delegate constructor + function SiringClockAuction(address _nftAddr, uint256 _cut) public + ClockAuction(_nftAddr, _cut) {} + + /// @dev Creates and begins a new auction. Since this function is wrapped, + /// require sender to be KittyCore contract. + /// @param _tokenId - ID of token to auction, sender must be owner. + /// @param _startingPrice - Price of item (in wei) at beginning of auction. + /// @param _endingPrice - Price of item (in wei) at end of auction. + /// @param _duration - Length of auction (in seconds). + /// @param _seller - Seller, if not the message sender + function createAuction( + uint256 _tokenId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration, + address _seller + ) + external + { + // Sanity check that no inputs overflow how many bits we've allocated + // to store them in the auction struct. + require(_startingPrice == uint256(uint128(_startingPrice))); + require(_endingPrice == uint256(uint128(_endingPrice))); + require(_duration == uint256(uint64(_duration))); + + require(msg.sender == address(nonFungibleContract)); + _escrow(_seller, _tokenId); + Auction memory auction = Auction( + _seller, + uint128(_startingPrice), + uint128(_endingPrice), + uint64(_duration), + uint64(now) + ); + _addAuction(_tokenId, auction); + } + + /// @dev Places a bid for siring. Requires the sender + /// is the KittyCore contract because all bid methods + /// should be wrapped. Also returns the kitty to the + /// seller rather than the winner. + function bid(uint256 _tokenId) + external + payable + { + require(msg.sender == address(nonFungibleContract)); + address seller = tokenIdToAuction[_tokenId].seller; + // _bid checks that token ID is valid and will throw if bid fails + _bid(_tokenId, msg.value); + // We transfer the kitty back to the seller, the winner will get + // the offspring + _transfer(seller, _tokenId); + } + +} + + + + + +/// @title Clock auction modified for sale of kitties +/// @notice We omit a fallback function to prevent accidental sends to this contract. +contract SaleClockAuction is ClockAuction { + + // @dev Sanity check that allows us to ensure that we are pointing to the + // right auction in our setSaleAuctionAddress() call. + bool public isSaleClockAuction = true; + + // Tracks last 5 sale price of gen0 kitty sales + uint256 public gen0SaleCount; + uint256[5] public lastGen0SalePrices; + + // Delegate constructor + function SaleClockAuction(address _nftAddr, uint256 _cut) public + ClockAuction(_nftAddr, _cut) {} + + /// @dev Creates and begins a new auction. + /// @param _tokenId - ID of token to auction, sender must be owner. + /// @param _startingPrice - Price of item (in wei) at beginning of auction. + /// @param _endingPrice - Price of item (in wei) at end of auction. + /// @param _duration - Length of auction (in seconds). + /// @param _seller - Seller, if not the message sender + function createAuction( + uint256 _tokenId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration, + address _seller + ) + external + { + // Sanity check that no inputs overflow how many bits we've allocated + // to store them in the auction struct. + require(_startingPrice == uint256(uint128(_startingPrice))); + require(_endingPrice == uint256(uint128(_endingPrice))); + require(_duration == uint256(uint64(_duration))); + + require(msg.sender == address(nonFungibleContract)); + _escrow(_seller, _tokenId); + Auction memory auction = Auction( + _seller, + uint128(_startingPrice), + uint128(_endingPrice), + uint64(_duration), + uint64(now) + ); + _addAuction(_tokenId, auction); + } + + /// @dev Updates lastSalePrice if seller is the nft contract + /// Otherwise, works the same as default bid method. + function bid(uint256 _tokenId) + external + payable + { + // _bid verifies token ID size + address seller = tokenIdToAuction[_tokenId].seller; + uint256 price = _bid(_tokenId, msg.value); + _transfer(msg.sender, _tokenId); + + // If not a gen0 auction, exit + if (seller == address(nonFungibleContract)) { + // Track gen0 sale prices + lastGen0SalePrices[gen0SaleCount % 5] = price; + gen0SaleCount++; + } + } + + function averageGen0SalePrice() external view returns (uint256) { + uint256 sum = 0; + for (uint256 i = 0; i < 5; i++) { + sum += lastGen0SalePrices[i]; + } + return sum / 5; + } + +} + + +/// @title Handles creating auctions for sale and siring of kitties. +/// This wrapper of ReverseAuction exists only so that users can create +/// auctions with only one transaction. +contract KittyAuction is KittyBreeding { + + // @notice The auction contract variables are defined in KittyBase to allow + // us to refer to them in KittyOwnership to prevent accidental transfers. + // `saleAuction` refers to the auction for gen0 and p2p sale of kitties. + // `siringAuction` refers to the auction for siring rights of kitties. + + /// @dev Sets the reference to the sale auction. + /// @param _address - Address of sale contract. + function setSaleAuctionAddress(address _address) external onlyCEO { + SaleClockAuction candidateContract = SaleClockAuction(_address); + + // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 + require(candidateContract.isSaleClockAuction()); + + // Set the new contract address + saleAuction = candidateContract; + } + + /// @dev Sets the reference to the siring auction. + /// @param _address - Address of siring contract. + function setSiringAuctionAddress(address _address) external onlyCEO { + SiringClockAuction candidateContract = SiringClockAuction(_address); + + // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 + require(candidateContract.isSiringClockAuction()); + + // Set the new contract address + siringAuction = candidateContract; + } + + /// @dev Put a kitty up for auction. + /// Does some ownership trickery to create auctions in one tx. + function createSaleAuction( + uint256 _kittyId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration + ) + external + whenNotPaused + { + // Auction contract checks input sizes + // If kitty is already on any auction, this will throw + // because it will be owned by the auction contract. + require(_owns(msg.sender, _kittyId)); + // Ensure the kitty is not pregnant to prevent the auction + // contract accidentally receiving ownership of the child. + // NOTE: the kitty IS allowed to be in a cooldown. + require(!isPregnant(_kittyId)); + _approve(_kittyId, saleAuction); + // Sale auction throws if inputs are invalid and clears + // transfer and sire approval after escrowing the kitty. + saleAuction.createAuction( + _kittyId, + _startingPrice, + _endingPrice, + _duration, + msg.sender + ); + } + + /// @dev Put a kitty up for auction to be sire. + /// Performs checks to ensure the kitty can be sired, then + /// delegates to reverse auction. + function createSiringAuction( + uint256 _kittyId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration + ) + external + whenNotPaused + { + // Auction contract checks input sizes + // If kitty is already on any auction, this will throw + // because it will be owned by the auction contract. + require(_owns(msg.sender, _kittyId)); + require(isReadyToBreed(_kittyId)); + _approve(_kittyId, siringAuction); + // Siring auction throws if inputs are invalid and clears + // transfer and sire approval after escrowing the kitty. + siringAuction.createAuction( + _kittyId, + _startingPrice, + _endingPrice, + _duration, + msg.sender + ); + } + + /// @dev Completes a siring auction by bidding. + /// Immediately breeds the winning matron with the sire on auction. + /// @param _sireId - ID of the sire on auction. + /// @param _matronId - ID of the matron owned by the bidder. + function bidOnSiringAuction( + uint256 _sireId, + uint256 _matronId + ) + external + payable + whenNotPaused + { + // Auction contract checks input sizes + require(_owns(msg.sender, _matronId)); + require(isReadyToBreed(_matronId)); + require(_canBreedWithViaAuction(_matronId, _sireId)); + + // Define the current price of the auction. + uint256 currentPrice = siringAuction.getCurrentPrice(_sireId); + require(msg.value >= currentPrice + autoBirthFee); + + // Siring auction will throw if the bid fails. + siringAuction.bid.value(msg.value - autoBirthFee)(_sireId); + _breedWith(uint32(_matronId), uint32(_sireId)); + } + + /// @dev Transfers the balance of the sale auction contract + /// to the KittyCore contract. We use two-step withdrawal to + /// prevent two transfer calls in the auction bid function. + function withdrawAuctionBalances() external onlyCLevel { + saleAuction.withdrawBalance(); + siringAuction.withdrawBalance(); + } +} + + +/// @title all functions related to creating kittens +contract KittyMinting is KittyAuction { + + // Limits the number of cats the contract owner can ever create. + uint256 public constant PROMO_CREATION_LIMIT = 5000; + uint256 public constant GEN0_CREATION_LIMIT = 45000; + + // Constants for gen0 auctions. + uint256 public constant GEN0_STARTING_PRICE = 10 finny; + uint256 public constant GEN0_AUCTION_DURATION = 1 days; + + // Counts the number of cats the contract owner has created. + uint256 public promoCreatedCount; + uint256 public gen0CreatedCount; + + /// @dev we can create promo kittens, up to a limit. Only callable by COO + /// @param _genes the encoded genes of the kitten to be created, any value is accepted + /// @param _owner the future owner of the created kittens. Default to contract COO + function createPromoKitty(uint256 _genes, address _owner) external onlyCOO { + address kittyOwner = _owner; + if (kittyOwner == address(0)) { + kittyOwner = cooAddress; + } + require(promoCreatedCount < PROMO_CREATION_LIMIT); + + promoCreatedCount++; + _createKitty(0, 0, 0, _genes, kittyOwner); + } + + /// @dev Creates a new gen0 kitty with the given genes and + /// creates an auction for it. + function createGen0Auction(uint256 _genes) external onlyCOO { + require(gen0CreatedCount < GEN0_CREATION_LIMIT); + + uint256 kittyId = _createKitty(0, 0, 0, _genes, address(this)); + _approve(kittyId, saleAuction); + + saleAuction.createAuction( + kittyId, + _computeNextGen0Price(), + 0, + GEN0_AUCTION_DURATION, + address(this) + ); + + gen0CreatedCount++; + } + + /// @dev Computes the next gen0 auction starting price, given + /// the average of the past 5 prices + 50%. + function _computeNextGen0Price() internal view returns (uint256) { + uint256 avePrice = saleAuction.averageGen0SalePrice(); + + // Sanity check to ensure we don't overflow arithmetic + require(avePrice == uint256(uint128(avePrice))); + + uint256 nextPrice = avePrice + (avePrice / 2); + + // We never auction for less than starting price + if (nextPrice < GEN0_STARTING_PRICE) { + nextPrice = GEN0_STARTING_PRICE; + } + + return nextPrice; + } +} + + +/// @title CryptoKitties: Collectible, breedable, and oh-so-adorable cats on the Ethereum blockchain. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev The main CryptoKitties contract, keeps track of kittens so they don't wander around and get lost. +contract KittyCore is KittyMinting { + + // This is the main CryptoKitties contract. In order to keep our code seperated into logical sections, + // we've broken it up in two ways. First, we have several seperately-instantiated sibling contracts + // that handle auctions and our super-top-secret genetic combination algorithm. The auctions are + // seperate since their logic is somewhat complex and there's always a risk of subtle bugs. By keeping + // them in their own contracts, we can upgrade them without disrupting the main contract that tracks + // kitty ownership. The genetic combination algorithm is kept seperate so we can open-source all of + // the rest of our code without making it _too_ easy for folks to figure out how the genetics work. + // Don't worry, I'm sure someone will reverse engineer it soon enough! + // + // Secondly, we break the core contract into multiple files using inheritence, one for each major + // facet of functionality of CK. This allows us to keep related code bundled together while still + // avoiding a single giant file with everything in it. The breakdown is as follows: + // + // - KittyBase: This is where we define the most fundamental code shared throughout the core + // functionality. This includes our main data storage, constants and data types, plus + // internal functions for managing these items. + // + // - KittyAccessControl: This contract manages the various addresses and constraints for operations + // that can be executed only by specific roles. Namely CEO, CFO and COO. + // + // - KittyOwnership: This provides the methods required for basic non-fungible token + // transactions, following the draft ERC-721 spec (https://github.com/ethereum/EIPs/issues/721). + // + // - KittyBreeding: This file contains the methods necessary to breed cats together, including + // keeping track of siring offers, and relies on an external genetic combination contract. + // + // - KittyAuctions: Here we have the public methods for auctioning or bidding on cats or siring + // services. The actual auction functionality is handled in two sibling contracts (one + // for sales and one for siring), while auction creation and bidding is mostly mediated + // through this facet of the core contract. + // + // - KittyMinting: This final facet contains the functionality we use for creating new gen0 cats. + // We can make up to 5000 "promo" cats that can be given away (especially important when + // the community is new), and all others can only be created and then immediately put up + // for auction via an algorithmically determined starting price. Regardless of how they + // are created, there is a hard limit of 50k gen0 cats. After that, it's all up to the + // community to breed, breed, breed! + + // Set in case the core contract is broken and an upgrade is required + address public newContractAddress; + + /// @notice Creates the main CryptoKitties smart contract instance. + function KittyCore() public { + // Starts paused. + paused = true; + + // the creator of the contract is the initial CEO + ceoAddress = msg.sender; + + // the creator of the contract is also the initial COO + cooAddress = msg.sender; + + // start with the mythical kitten 0 - so we don't have generation-0 parent issues + _createKitty(0, 0, 0, uint256(-1), address(0)); + } + + /// @dev Used to mark the smart contract as upgraded, in case there is a serious + /// breaking bug. This method does nothing but keep track of the new contract and + /// emit a message indicating that the new address is set. It's up to clients of this + /// contract to update to the new contract address in that case. (This contract will + /// be paused indefinitely if such an upgrade takes place.) + /// @param _v2Address new address + function setNewAddress(address _v2Address) external onlyCEO whenPaused { + // See README.md for updgrade plan + newContractAddress = _v2Address; + ContractUpgrade(_v2Address); + } + + /// @notice No tipping! + /// @dev Reject all Ether from being sent here, unless it's from one of the + /// two auction contracts. (Hopefully, we can prevent user accidents.) + function() external payable { + require( + msg.sender == address(saleAuction) || + msg.sender == address(siringAuction) + ); + } + + /// @notice Returns all the relevant information about a specific kitty. + /// @param _id The ID of the kitty of interest. + function getKitty(uint256 _id) + external + view + returns ( + bool isGestating, + bool isReady, + uint256 cooldownIndex, + uint256 nextActionAt, + uint256 siringWithId, + uint256 birthTime, + uint256 matronId, + uint256 sireId, + uint256 generation, + uint256 genes + ) { + Kitty storage kit = kitties[_id]; + + // if this variable is 0 then it's not gestating + isGestating = (kit.siringWithId != 0); + isReady = (kit.cooldownEndBlock <= block.number); + cooldownIndex = uint256(kit.cooldownIndex); + nextActionAt = uint256(kit.cooldownEndBlock); + siringWithId = uint256(kit.siringWithId); + birthTime = uint256(kit.birthTime); + matronId = uint256(kit.matronId); + sireId = uint256(kit.sireId); + generation = uint256(kit.generation); + genes = kit.genes; + } + + /// @dev Override unpause so it requires all external contract addresses + /// to be set before contract can be unpaused. Also, we can't have + /// newContractAddress set either, because then the contract was upgraded. + /// @notice This is public rather than external so we can call super.unpause + /// without using an expensive CALL. + function unpause(address toAddress, uint256 tokenValue, trcToken tokenId) public onlyCEO whenPaused returns (uint256 r) { + require(saleAuction != address(0)); + require(siringAuction != address(0)); + require(geneScience != address(0)); + require(newContractAddress == address(0)); + toAddress.transferToken(tokenValue, tokenId); + r = address(this).tokenBalance(tokenId); + // Actually unpause the contract. + super.unpause(); + } + + // @dev Allows the CFO to capture the balance available to the contract. + function withdrawBalance() external onlyCFO { + uint256 balance = this.balance; + // Subtract all the currently pregnant kittens we have, plus 1 of margin. + uint256 subtractFees = (pregnantKitties + 1) * autoBirthFee; + + if (balance > subtractFees) { + cfoAddress.send(balance - subtractFees); + } + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/assertExceptiontest1DivideInt.sol b/src/test/resources/soliditycode_v0.4.25/assertExceptiontest1DivideInt.sol new file mode 100644 index 00000000000..8ed20cd1cab --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/assertExceptiontest1DivideInt.sol @@ -0,0 +1,7 @@ +pragma solidity ^0.4.0; + +contract divideIHaveArgsReturnStorage{ +function divideIHaveArgsReturn(int x,int y) public returns (int z) { +return z = x / y; +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/assertExceptiontest2FindArgsContractMinTest.sol b/src/test/resources/soliditycode_v0.4.25/assertExceptiontest2FindArgsContractMinTest.sol new file mode 100644 index 00000000000..af54558bc98 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/assertExceptiontest2FindArgsContractMinTest.sol @@ -0,0 +1,10 @@ +pragma solidity ^0.4.0; +contract findArgsIContract{ +function findArgsByIndex1(uint i)public returns (uint z) { +uint[] memory a = new uint[](3); +a[0]=1; +a[1]=2; +a[2]=3; +return a[i]; +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/assertExceptiontest3ByteMinContract.sol b/src/test/resources/soliditycode_v0.4.25/assertExceptiontest3ByteMinContract.sol new file mode 100644 index 00000000000..d2e8637612d --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/assertExceptiontest3ByteMinContract.sol @@ -0,0 +1,11 @@ +pragma solidity ^0.4.0; +contract byteContract { +bytes b; +function testBytesGet(uint i) returns (bytes1){ +b = new bytes(3); +b[0]=12; +b[1]=13; +b[2]=14; +return b[i]; +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/assertExceptiontest4Enum.sol b/src/test/resources/soliditycode_v0.4.25/assertExceptiontest4Enum.sol new file mode 100644 index 00000000000..5d7164d27d1 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/assertExceptiontest4Enum.sol @@ -0,0 +1,13 @@ +pragma solidity ^0.4.4; + +contract enumContract { + enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill } + ActionChoices _choice; + function setGoStraight(ActionChoices choice) public { + _choice = choice; + } + + function getChoice() public returns (ActionChoices) { + return _choice; + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/assertExceptiontest5MoveRight.sol b/src/test/resources/soliditycode_v0.4.25/assertExceptiontest5MoveRight.sol new file mode 100644 index 00000000000..c0d15a7aa09 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/assertExceptiontest5MoveRight.sol @@ -0,0 +1,7 @@ +pragma solidity ^0.4.0; + +contract binaryRightContract{ + function binaryMoveR(int i)public returns (int z) { + return z = 5 >> i; + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/assertExceptiontest6UninitializedContract.sol b/src/test/resources/soliditycode_v0.4.25/assertExceptiontest6UninitializedContract.sol new file mode 100644 index 00000000000..dbfa3e01bc0 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/assertExceptiontest6UninitializedContract.sol @@ -0,0 +1,27 @@ +pragma solidity ^0.4.0; +contract uni { +function b(int x, int y) internal returns (int) +{ + return x * y; +} + +function test1() external returns (int) +{ + // Variable containing a function pointer + function (int, int) internal returns (int) funcPtr; + + funcPtr = b; + + // This call to funcPtr will succeed + return funcPtr(4, 5); +} + +function test2() external returns (int) +{ + // Variable containing a function pointer + function (int, int) internal returns (int) funcPtr; + + // This call will fail because funcPtr is still a zero-initialized function pointer + return funcPtr(4, 5); +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/assertExceptiontest7TestAssertContract.sol b/src/test/resources/soliditycode_v0.4.25/assertExceptiontest7TestAssertContract.sol new file mode 100644 index 00000000000..842b8c174e5 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/assertExceptiontest7TestAssertContract.sol @@ -0,0 +1,17 @@ +pragma solidity ^0.4.0; + + +contract TestThrowsContract{ + function testAssert(){ + assert(1==2); + } + function testRequire(){ + require(2==1); + } + function testRevert(){ + revert(); + } + function testThrow(){ + throw; + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/codeSaftySupport.sol b/src/test/resources/soliditycode_v0.4.25/codeSaftySupport.sol new file mode 100644 index 00000000000..7ae081877b6 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/codeSaftySupport.sol @@ -0,0 +1,19 @@ +pragma solidity ^0.4.24; + +contract IllegalDecorate { + +constructor() payable public{} + +function() payable external{} + +event log(uint256); + +function transferToken(address toAddress, uint256 tokenValue) public payable { +emit log(msg.value); +emit log(msg.tokenvalue); +emit log(msg.tokenid); +toAddress.transferToken(msg.tokenvalue, msg.tokenid); +toAddress.transfer(msg.value); +} + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/codeSaftyUnsupport.sol b/src/test/resources/soliditycode_v0.4.25/codeSaftyUnsupport.sol new file mode 100644 index 00000000000..ff561614780 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/codeSaftyUnsupport.sol @@ -0,0 +1,50 @@ + pragma solidity ^0.4.24; +contract SubC { +event log(string); + +function () payable {} + +function receiveToken() payable {} + +function getBalance() constant public returns (uint256 r){ +r = address(this).balance; +} +} +contract UseDot { +constructor() payable public{} +function() payable public{} +mapping(address => mapping(trcToken => uint256)) sender_tokens; + +function trigger1(address addr) payable public { + //SubC(addr).call.value(1000).tokenId(0x6e6d62)(bytes4(sha3("receiveToken()"))); // ERROR +} + +function trigger2(address addr) payable public { + //addr.transferToken.value(10)(10, 0x6e6d62); // ERROR +} + +function trigger3(address addr) payable public { +// SubC(addr).receiveToken.tokenvalue(10)(); // ERROR +} + +function trigger4(address addr) payable public { +// SubC(addr).receiveToken.tokenId(0x6e6d62)(); // ERROR +} + +function trigger5(address addr) payable public { +SubC(addr).receiveToken.value(10)(); +} +function trigger6(address addr, trcToken tokenId) payable public { +SubC(addr).call.value(1000)(bytes4(sha3("transferToken(uint256, trcToken)")), 10, tokenId); +} + +function trigger7(address addr) payable public { + //sender_tokens[msg.sender][msg.tokenid] += msg.tokenvalue; // compile success, no necessary to trigger +} +function trigger8(address addr) public payable returns(bytes r){ + //r = msg.data; // compile success, no necessary to trigger +} +function getBalance() public returns (uint256 r){ +r = address(this).balance; +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractGetterContract.sol b/src/test/resources/soliditycode_v0.4.25/contractGetterContract.sol new file mode 100644 index 00000000000..deed0aeabd2 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractGetterContract.sol @@ -0,0 +1,17 @@ +//pragma solidity ^0.4.0; + + +contract getterContract{ + +constructor() public payable{} +function() external payable{} + +uint public c = msg.value; + +function getDataUsingAccessor() returns (uint){ + +return c; + +} + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractGrammar001test1Grammar001.sol b/src/test/resources/soliditycode_v0.4.25/contractGrammar001test1Grammar001.sol new file mode 100644 index 00000000000..f433ed3585f --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractGrammar001test1Grammar001.sol @@ -0,0 +1,14 @@ +pragma solidity ^0.4.16; +contract FunctionSelector { + function select(bool useB, uint x) public returns (uint z) { + var f = a; + if (useB) f = b; + return f(x); + } +function a(uint x) public returns (uint z) { + return x * x; + } +function b(uint x) public returns (uint z) { + return 2 * x; + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractGrammar001test2Grammar002.sol b/src/test/resources/soliditycode_v0.4.25/contractGrammar001test2Grammar002.sol new file mode 100644 index 00000000000..da9ff8caa56 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractGrammar001test2Grammar002.sol @@ -0,0 +1,44 @@ +pragma solidity ^0.4.16; +library Set { + // We define a new struct datatype that will be used to + // hold its data in the calling contract. + struct Data { mapping(uint => bool) flags; } + + // Note that the first parameter is of type "storage + // reference" and thus only its storage address and not + // its contents is passed as part of the call. This is a + // special feature of library functions. It is idiomatic + // to call the first parameter 'self', if the function can + // be seen as a method of that object. + function insert(Data storage self, uint value) public returns (bool) { + if (self.flags[value]) + return false; // already there + self.flags[value] = true; + return true; + } + + function remove(Data storage self, uint value) public returns (bool) { + if (!self.flags[value]) + return false; // not there + self.flags[value] = false; + return true; + } + + function contains(Data storage self, uint value) public returns (bool) { + return self.flags[value]; + } +} + + +contract C { + Set.Data knownValues; + + function register(uint value) { + // The library functions can be called without a + // specific instance of the library, since the + // "instance" will be the current contract. + if (!Set.insert(knownValues, value)) + throw; + } + // In this contract, we can also directly access knownValues.flags, if we want. +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractGrammar001test3Grammar003.sol b/src/test/resources/soliditycode_v0.4.25/contractGrammar001test3Grammar003.sol new file mode 100644 index 00000000000..4d3f87ebe3e --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractGrammar001test3Grammar003.sol @@ -0,0 +1,44 @@ +pragma solidity ^0.4.11; + +library Set { + struct Data { mapping(uint => bool) flags; } + + function insert(Data storage self, uint value) public + returns (bool) + { + if (self.flags[value]) + return false; // already there + self.flags[value] = true; + return true; + } + + function remove(Data storage self, uint value) public + returns (bool) + { + if (!self.flags[value]) + return false; // not there + self.flags[value] = false; + return true; + } + + function contains(Data storage self, uint value) public + returns (bool) + { + return self.flags[value]; + } +} + + +contract C { + using Set for Set.Data; // this is the crucial change + Set.Data knownValues; + + function register(uint value) { + // Here, all variables of type Set.Data have + // corresponding member functions. + // The following function call is identical to + // Set.insert(knownValues, value) + if (!knownValues.insert(value)) + throw; + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractGrammar001test4Grammar004.sol b/src/test/resources/soliditycode_v0.4.25/contractGrammar001test4Grammar004.sol new file mode 100644 index 00000000000..78bc620c81f --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractGrammar001test4Grammar004.sol @@ -0,0 +1,31 @@ +pragma solidity ^0.4.0; + +library Search { + function indexOf(uint[] storage self, uint value) public returns (uint) { + for (uint i = 0; i < self.length; i++) + if (self[i] == value) return i; + return uint(-1); + } +} + + +contract C { + using Search for uint[]; + uint[] public data; + + function append(uint value) { + data.push(value); + } + + function replace(uint _old, uint _new) { + // This performs the library function call + uint index = data.indexOf(_old); + if (index == uint(-1)) + data.push(_new); + else + data[index] = _new; + } + function getData(uint256 index) public returns(uint256){ + return data[index]; + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractGrammar001test5Grammar006.sol b/src/test/resources/soliditycode_v0.4.25/contractGrammar001test5Grammar006.sol new file mode 100644 index 00000000000..5bba3d4bba0 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractGrammar001test5Grammar006.sol @@ -0,0 +1,36 @@ + pragma solidity ^0.4.0; +contract InfoFeed { +function d1(uint x){ + assembly{ + function f(x) -> y { switch x case 0 { y := 1 } default { y := mul(x, f(sub(x, 1))) } } + } + } + function d2(uint x){ + assembly { x := mul(1, add(2, 3))} + } + function f(uint x) { + assembly { x := sub(x, 1) } + + } + function d(uint x){ + assembly{ + let x := add(2, 3) let y := mload(0x40) x := add(x, y) + } + } + function d4(uint x){ + assembly{let x := 10 repeat: x := sub(x, 1) jumpi(repeat, eq(x, 0)) + } + } + function d5(uint x){ + assembly{ + function f(x) -> y { switch x case 0 { y := mul(x, 2) } default { y := 0 } } + + } + } + + function d6(uint x){ + assembly{ + function f(x) -> y { for { let i := 0 } lt(i, x) { i := add(i, 1) } { y := mul(2, y) } } + } + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractGrammar002test1Grammar007_1.sol b/src/test/resources/soliditycode_v0.4.25/contractGrammar002test1Grammar007_1.sol new file mode 100644 index 00000000000..752d3613be2 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractGrammar002test1Grammar007_1.sol @@ -0,0 +1,60 @@ +pragma solidity ^0.4.19; +contract Doug{ + mapping (bytes32 => uint) public contracts; + function Doug() { + contracts['hww'] = 1; + contracts['brian'] = 2; + contracts['zzy'] = 7; + } + + function getDougName(string _name) public view returns(string) { + return _name; + } + + function getDougAge(uint _age) public pure returns(uint) { + return 3 ** _age; + } +} + +contract DogInterface { + function getDougAge(uint _age) returns (uint); + function contracts(bytes32 name) returns (uint); +} +contract main{ + + event FetchContract(address dogInterfaceAddress, address sender, bytes32 name); + + address public DOUG; + + address dogInterfaceAddress; + DogInterface dogContract ; + + function setDOUG(address _doug) { + DOUG = _doug; + } + + constructor(address addr) public{ + dogInterfaceAddress = addr; + dogContract = DogInterface(dogInterfaceAddress); + } + + function dougOfage(uint _age) public view returns(uint) { + + uint num = dogContract.getDougAge(_age); + return _age+num; + // return num; + } + + function uintOfName(bytes32 _name) returns (uint) { + + dogContract.contracts(_name); + FetchContract(dogInterfaceAddress, msg.sender, _name); + + } + + // function getTest(string _name) public view returns(string) { + // string memory newName = _name ; + // DogInterface(DOUG).getDougName(newName); + // return newName; + // } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractGrammar002test1Grammar007_2.sol b/src/test/resources/soliditycode_v0.4.25/contractGrammar002test1Grammar007_2.sol new file mode 100644 index 00000000000..8078507e7b2 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractGrammar002test1Grammar007_2.sol @@ -0,0 +1,60 @@ +pragma solidity ^0.4.19; +contract Doug{ + mapping (bytes32 => uint) public contracts; + function Doug() { + contracts['hww'] = 1; + contracts['brian'] = 2; + contracts['zzy'] = 7; + } + + function getDougName(string _name) public view returns(string) { + return _name; + } + + function getDougAge(uint _age) public pure returns(uint) { + return 3 ** _age; + } +} + +contract DogInterface { + function getDougAge(uint _age) returns (uint); + function contracts(bytes32 name) returns (uint); +} +contract main{ + + event FetchContract(address dogInterfaceAddress, address sender, bytes32 name); + + address public DOUG; + + address dogInterfaceAddress; + DogInterface dogContract ; + + function setDOUG(address _doug) { + DOUG = _doug; + } + + constructor(address addr) public{ + dogInterfaceAddress = addr; + dogContract = DogInterface(dogInterfaceAddress); + } + + function dougOfage(uint _age) public view returns(uint) { + + uint num = dogContract.getDougAge(_age); + return _age+num; + // return num; + } + + function uintOfName(bytes32 _name) returns (uint) { + + dogContract.contracts(_name); + FetchContract(dogInterfaceAddress, msg.sender, _name); + + } + + // function getTest(string _name) public view returns(string) { + // string memory newName = _name ; + // DogInterface(DOUG).getDougName(newName); + // return newName; + // } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractGrammar002test2Grammar008.sol b/src/test/resources/soliditycode_v0.4.25/contractGrammar002test2Grammar008.sol new file mode 100644 index 00000000000..fb4338de0d8 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractGrammar002test2Grammar008.sol @@ -0,0 +1,14 @@ +pragma solidity ^0.4.19; +contract Feline { + function utterance() public returns (bytes32); + + function getContractName() public returns (string){ + return "Feline"; + } +} + + +contract Cat is Feline { + function utterance() public returns (bytes32) { return "miaow"; } + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractGrammar002test3Grammar010.sol b/src/test/resources/soliditycode_v0.4.25/contractGrammar002test3Grammar010.sol new file mode 100644 index 00000000000..43ff2e0aef3 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractGrammar002test3Grammar010.sol @@ -0,0 +1,10 @@ +pragma solidity ^0.4.0; +contract InfoFeed { +function info() public payable returns (uint ret) { return 42; } +} +contract Consumer { +constructor() payable public{} +InfoFeed feed; +function setFeed(address addr) public { feed = InfoFeed(addr); } +function callFeed() public payable{ feed.info.value(10).gas(800)(); } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractGrammar002test4Grammar011.sol b/src/test/resources/soliditycode_v0.4.25/contractGrammar002test4Grammar011.sol new file mode 100644 index 00000000000..0b673512248 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractGrammar002test4Grammar011.sol @@ -0,0 +1,11 @@ +pragma solidity ^0.4.0; +contract C { +function f(uint key, uint value) public returns(uint) { +return key; +// do something +} +function g() public { +// named arguments +f({value: 2, key: 3}); +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractGrammar002test4Grammar012.sol b/src/test/resources/soliditycode_v0.4.25/contractGrammar002test4Grammar012.sol new file mode 100644 index 00000000000..3c72e608e24 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractGrammar002test4Grammar012.sol @@ -0,0 +1,24 @@ +pragma solidity ^0.4.24; +contract rTest { +function info() public payable returns (uint,address,bytes4,uint,uint,uint,address,uint) { +//function info() public payable returns (address ,uint,uint,uint,bytes32,uint,bytes,uint,address,bytes4,uint,uint,uint,address,uint) { +//var a = block.coinbase ; +//var b = block.difficulty; +//var c = block.gaslimit; +//var d = block.number; +//var e = block.blockhash(0); +//var e = d; +//var f = block.timestamp; +//bytes memory g = msg.data; +var h = msg.gas; +var i = msg.sender; +var j = msg.sig; +var k = msg.value; +var l = now; +var m = tx.gasprice; +var n = tx.origin; +var o = this.balance; +return (h,i,j,k,l,m,n,o); +//return (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o); +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractGrammar002test6Grammar013.sol b/src/test/resources/soliditycode_v0.4.25/contractGrammar002test6Grammar013.sol new file mode 100644 index 00000000000..f29197bccc3 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractGrammar002test6Grammar013.sol @@ -0,0 +1,22 @@ +pragma solidity ^0.4.4; +contract Counter { +uint count = 0; +address owner; +function Counter() { +owner = msg.sender; +} +function increment() public { +uint step = 10; +if (owner == msg.sender) { +count = count + step; +} +} +function getCount() public returns (uint) { +return count; +} +function kill() { +if (owner == msg.sender) { +selfdestruct(owner); +} +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractGrammar003test1Grammar014.sol b/src/test/resources/soliditycode_v0.4.25/contractGrammar003test1Grammar014.sol new file mode 100644 index 00000000000..c55b5b391a3 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractGrammar003test1Grammar014.sol @@ -0,0 +1,59 @@ +pragma solidity ^0.4.4; +contract A { +uint256 public numberForB; +address public senderForB; +function callTest(address bAddress, uint256 _number) { +bAddress.call(bytes4(sha3("setValue(uint256)")), _number); // B's storage is set, A is not modified +} +function callcodeTest(address bAddress, uint256 _number) { +bAddress.callcode(bytes4(sha3("setValue(uint256)")), _number); // A's storage is set, B is not modified +} +function delegatecallTest(address bAddress, uint256 _number) { +bAddress.delegatecall(bytes4(sha3("setValue(uint256)")), _number); // A's storage is set, B is not modified +} + +function callAddTest(address bAddress) { +bAddress.call(bytes4(sha3("add()"))); // B's storage is set, A is not modified +bAddress.call(bytes4(sha3("add()"))); // B's storage is set, A is not modified +} +function getnumberForB() public returns(uint256){ + return numberForB; + } + function getsenderForB() public returns(address){ + return senderForB; + } +} +contract B { +uint256 public numberForB; +address public senderForB; +address public addr11; +mapping(uint256=>address) public addr1; +mapping(uint256=>address) public addr2; +function setValue(uint256 _number) { +numberForB = _number; +senderForB = msg.sender; +// senderForB is A if invoked by A's callTest. B's storage will be updated +// senderForB is A if invoked by A's callcodeTest. None of B's storage is updated +// senderForB is OWNER if invoked by A's delegatecallTest. None of B's storage is updated +} + +function add() public{ +numberForB=numberForB+1; +C c1 = new C(); +addr1[numberForB]=c1.getAddress(); +addr11 = c1.getAddress(); +C c2 = new C(); +addr2[numberForB] = c2.getAddress(); +} +function getnumberForB() public returns(uint256){ + return numberForB; + } + function getsenderForB() public returns(address){ + return senderForB; + } +} +contract C { +function getAddress() public view returns(address){ +return address(this); +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractGrammar003test2Grammar015.sol b/src/test/resources/soliditycode_v0.4.25/contractGrammar003test2Grammar015.sol new file mode 100644 index 00000000000..4e704628f4b --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractGrammar003test2Grammar015.sol @@ -0,0 +1,37 @@ +pragma solidity ^0.4.0; + +contract ExecuteFallback{ + + //回退事件,会把调用的数据打印出来 + event FallbackCalled(bytes data); + //fallback函数,注意是没有名字的,没有参数,没有返回值的 + function(){ + FallbackCalled(msg.data); + } + + //调用已存在函数的事件,会把调用的原始数据,请求参数打印出来 + event ExistFuncCalled(bytes data, uint256 para); + //一个存在的函数 + function existFunc(uint256 para){ + ExistFuncCalled(msg.data, para); + } + + // 模拟从外部对一个存在的函数发起一个调用,将直接调用函数 + function callExistFunc(){ + bytes4 funcIdentifier = bytes4(keccak256("existFunc(uint256)")); + this.call(funcIdentifier, uint256(1)); + } + + //模拟从外部对一个不存在的函数发起一个调用,由于匹配不到函数,将调用回退函数 + function callNonExistFunc(){ + bytes4 funcIdentifier = bytes4(keccak256("functionNotExist()")); + this.call(funcIdentifier); + } + + function ExistFuncCalledTopic() view returns(bytes32){ + return keccak256("ExistFuncCalled(bytes,uint256)"); + } + function FallbackCalledTopic() view returns(bytes32){ + return keccak256("FallbackCalled(bytes)"); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractGrammar003test3Grammar016.sol b/src/test/resources/soliditycode_v0.4.25/contractGrammar003test3Grammar016.sol new file mode 100644 index 00000000000..a39a0a08d96 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractGrammar003test3Grammar016.sol @@ -0,0 +1,23 @@ +pragma solidity ^0.4.0; +contract C { +uint private data; +function f(uint a) private returns(uint b) { return a + 1; } +function setData(uint a) public { data = a; } +function getData() public returns(uint) { return data; } +function compute(uint a, uint b) internal returns (uint) { return a+b; } +} +contract D { +function readData() public{ +C c = new C(); +//uint local = c.f(7); // error: member "f" is not visible +c.setData(3); +uint local = c.getData(); +// local = c.compute(3, 5); // error: member "compute" is not visible +} +} +contract E is C { +function g() public { +C c = new C(); +uint val = compute(3, 5); // access to internal member (from derived to parent contract) +} +} diff --git a/src/test/resources/soliditycode_v0.4.25/contractGrammar003test4Grammar017.sol b/src/test/resources/soliditycode_v0.4.25/contractGrammar003test4Grammar017.sol new file mode 100644 index 00000000000..3387a9c30bd --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractGrammar003test4Grammar017.sol @@ -0,0 +1,47 @@ +pragma solidity ^0.4.0; +contract CrowdFunding{ +struct Funder{ +address addr; +uint amount; +} + +struct Campaign{ +address beneficiary; +uint goal; +uint amount; +uint funderNum; +mapping(uint => Funder) funders; +} + +uint compaingnID; +mapping (uint => Campaign) campaigns; + +function candidate(address beneficiary, uint goal) returns (uint compaingnID){ +// initialize +campaigns[compaingnID++] = Campaign(beneficiary, goal, 0, 0); +} + +function vote(uint compaingnID) payable { +Campaign c = campaigns[compaingnID]; + +//another way to initialize +c.funders[c.funderNum++] = Funder({addr: msg.sender, amount: msg.value}); +c.amount += msg.value; +} + +function check(uint comapingnId) returns (bool){ +Campaign c = campaigns[comapingnId]; + +if(c.amount < c.goal){ +return false; +} + +uint amount = c.amount; +// incase send much more +c.amount = 0; +if(!c.beneficiary.send(amount)){ +throw; +} +return true; +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractGrammar003test5Grammar018.sol b/src/test/resources/soliditycode_v0.4.25/contractGrammar003test5Grammar018.sol new file mode 100644 index 00000000000..4fdaf52a29f --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractGrammar003test5Grammar018.sol @@ -0,0 +1,36 @@ +pragma solidity ^0.4.0; + + +contract Grammar18{ + function testAddmod() public returns (uint z) { + //计算(x + y)%k,其中以任意精度执行加法,并且不在2 ** 256处围绕 + z=addmod(2, 2, 3); + return z; + } + function testMulmod() public returns (uint z) { +//计算(x * y)%k,其中乘法以任意精度执行,并且不会在2 ** 256处循环。 + z=mulmod(2, 3, 4); + return z; + } + + function testKeccak256() public returns(bytes32){ + //计算的(紧凑)参数的Ethereum-SHA-3(Keccak-256)的散列 + return keccak256("11"); + } + + function testSha256() public returns(bytes32){ + //计算(紧密包装)参数的SHA-256散列 + return sha256("11"); + } + function testSha3() public returns(bytes32){ + //计算(紧密包装)参数的SHA-256散列 + return sha3("11"); + } + + function testRipemd160() public returns(bytes32){ + //计算(紧密包装)参数的RIPEMD-160哈希值 + return ripemd160("11"); + } + + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractGrammar003test6Grammar019.sol b/src/test/resources/soliditycode_v0.4.25/contractGrammar003test6Grammar019.sol new file mode 100644 index 00000000000..3b2d5f2263c --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractGrammar003test6Grammar019.sol @@ -0,0 +1,12 @@ +pragma solidity ^0.4.0; +contract timetest { + +function timetest() public { +require( 1 == 1 seconds); +require(1 minutes == 60 seconds); +require(1 hours == 60 minutes); +require(1 days == 24 hours); +require(1 weeks == 7 days); +require(1 years == 365 days); +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractGrammar003test7Grammar020.sol b/src/test/resources/soliditycode_v0.4.25/contractGrammar003test7Grammar020.sol new file mode 100644 index 00000000000..d5157c18c47 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractGrammar003test7Grammar020.sol @@ -0,0 +1,7 @@ +pragma solidity ^0.4.0; +contract trxtest { + +function test() public { +require(1 trx == 1000000 sun); +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractInnerContract.sol b/src/test/resources/soliditycode_v0.4.25/contractInnerContract.sol new file mode 100644 index 00000000000..02402acd217 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractInnerContract.sol @@ -0,0 +1,31 @@ +//pragma solidity ^0.4.0; + + + +contract InnerContract { + + + constructor() public payable{} + function() external payable{} + function messageI() payable returns (uint ret) { + + + + } + +} + + + +contract OuterContract { + + constructor() public payable{} + function() external payable{} + + function callInner(address addr) payable returns (uint) { + + return InnerContract(addr).messageI.value(1)(); + + } + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction001.sol b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction001.sol new file mode 100644 index 00000000000..1f13e067773 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction001.sol @@ -0,0 +1,42 @@ +pragma solidity ^0.4.24; + +contract A{ + constructor() payable public{} + function() payable public{} + function test1(address cAddr) public payable{ + B b1 = (new B).value(10)();//1.1 + B b2 = new B();//1.2 + b2.transfer(5);//1.3 + b2.callCGetZero(cAddr, 1);//1.4 + b2.callCGetZero(cAddr,2);//1.6 + } + function test2(address cAddress,uint256 amount) public payable{ + cAddress.call.value(amount)(bytes4(keccak256("newBAndTransfer()")));//2.1 + cAddress.call.value(amount + 1)(bytes4(keccak256("newBAndTransfer()")));//2.6 + } +} + +contract B{ + constructor() payable public{} + function() payable public{} + function getOne() payable returns(uint256){ + return 1; + } + function callCGetZero(address cAddress,uint256 amount){ + cAddress.call.value(amount)(bytes4(keccak256("getZero()")));//1.5,1.7 + } +} + +contract C{ + constructor() payable public{} + function() payable public{} + function getZero() payable public returns(uint256){ + return 0; + } + function newBAndTransfer() payable public returns(uint256){ + B b1 = (new B).value(7)();//2.2,2.7 + b1.getOne();//2.3,2.8 + B b2 = (new B).value(3)();//2.4,2.9 + b2.getOne();//2.5,2.10 + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction002.sol b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction002.sol new file mode 100644 index 00000000000..b5fd94f5a0e --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction002.sol @@ -0,0 +1,20 @@ +pragma solidity ^0.4.24; + +contract A{ + constructor() payable public{} + function() payable public{} + + function test2(address cAddress,uint256 amount) public payable{ + cAddress.call.value(amount)();//2.1 + } +} + + +contract C{ + constructor() payable public{} + function() payable public{} + function getZero() payable public returns(uint256){ + return 0; + } + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction003.sol b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction003.sol new file mode 100644 index 00000000000..ab8841419e7 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction003.sol @@ -0,0 +1,31 @@ +pragma solidity ^0.4.24; + + contract A{ + uint256 public num = 0; + constructor() public payable{} + function transfer() payable public{ + B b = (new B).value(10)();//1 + + } + function getBalance() returns(uint256){ + return this.balance; + } + } + contract B{ + uint256 public num = 0; + function f() payable returns(bool) { + return true; + } + constructor() public payable {} + function payC(address c, bool isRevert) public{ + c.transfer(1);//4 + if (isRevert) { + revert(); + } + } + function getBalance() public returns(uint256){ + return this.balance; + } + function () payable{} + } + diff --git a/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction004.sol b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction004.sol new file mode 100644 index 00000000000..8a03691b172 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction004.sol @@ -0,0 +1,24 @@ +pragma solidity ^0.4.24; + +contract A{ + constructor () payable public{} + function suicide(address toAddress) public payable{ + selfdestruct(toAddress); + } + function () payable public{} + function getBalance() public view returns(uint256){ + return this.balance; + } +} +contract B{ + function kill(address contractAddres, address toAddress) payable public { + contractAddres.call(bytes4(keccak256("suicide(address)")),address(this)); + } + function kill2(){ + A a = new A(); + a.suicide(this); + } + function getBalance() public view returns(uint256){ + return this.balance; + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction005.sol b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction005.sol new file mode 100644 index 00000000000..d4042dba94a --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction005.sol @@ -0,0 +1,54 @@ +pragma solidity ^0.4.24; + +contract A{ + constructor() payable public{} + function() payable public{} + function test1() public payable{ + B b1 = (new B).value(10)();//1.1 + b1.callCGetZero(false); + b1.callCGetZero(true);//1.4 + } + function test2() public payable{ + C c1 = (new C).value(10)();//1.1 + c1.newBAndTransfer(false); + c1.newBAndTransfer(true);//1.4 + + } + function getBalance() view public returns(uint256){ + return this.balance; + } +} + +contract B{ + constructor() payable public{} + function() payable public{} + function getOne() payable returns(uint256){ + return 1; + } + function callCGetZero(bool success) payable{ + if(!success){ + assert(1==2); + } + } + function getBalance() view public returns(uint256){ + return this.balance; + } +} + +contract C{ + uint256 public flag=0; + constructor() payable public{} + function() payable public{} + function getZero() payable public returns(uint256){ + return 0; + } + function newBAndTransfer(bool success) payable public returns(uint256){ + flag = 1; + if(!success){ + require(2==1); + } + } + function getFlag() public returns(uint256){ + return flag; + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction006.sol b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction006.sol new file mode 100644 index 00000000000..885966df74f --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction001testInternalTransaction006.sol @@ -0,0 +1,54 @@ +pragma solidity ^0.4.24; + +contract A{ + constructor() payable public{} + function() payable public{} + function test1() public payable{ + B b1 = (new B).value(10)();//1.1 + b1.callCGetZero(true);//1.4 + b1.callCGetZero(false); + } + function test2() public payable{ + C c1 = (new C).value(10)();//1.1 + c1.newBAndTransfer(true);//1.4 + c1.newBAndTransfer(false); + + } + function getBalance() view public returns(uint256){ + return this.balance; + } +} + +contract B{ + constructor() payable public{} + function() payable public{} + function getOne() payable returns(uint256){ + return 1; + } + function callCGetZero(bool success) payable{ + if(!success){ + assert(1==2); + } + } + function getBalance() view public returns(uint256){ + return this.balance; + } +} + +contract C{ + uint256 public flag=0; + constructor() payable public{} + function() payable public{} + function getZero() payable public returns(uint256){ + return 0; + } + function newBAndTransfer(bool success) payable public returns(uint256){ + flag = 1; + if(!success){ + require(2==1); + } + } + function getFlag() public returns(uint256){ + return flag; + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test1InternalTransaction007.sol b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test1InternalTransaction007.sol new file mode 100644 index 00000000000..fc1eb39c36e --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test1InternalTransaction007.sol @@ -0,0 +1,38 @@ +pragma solidity ^0.4.24; + +contract A{ + constructor() payable public{} + function() payable public{} + function test1(address cAddr) public payable{ + B b1 = (new B).value(10)();//1.1 + B b2 = new B();//1.2 + b2.transfer(5);//1.3 + b2.callCGetZero();//1.4 + } + function test2(address cAddress,uint256 amount) public payable{ + cAddress.call.value(amount)(bytes4(keccak256("newBAndTransfer()")));//2.1 + } +} + +contract B{ + constructor() payable public{} + function() payable public{} + function getOne() payable returns(uint256){ + return 1; + } + function callCGetZero(){ + assert(1==2); + + } +} + +contract C{ + constructor() payable public{} + function() payable public{} + function getZero() payable public returns(uint256){ + return 0; + } + function newBAndTransfer() payable public returns(uint256){ + require(2==1); + } +} diff --git a/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test2InternalTransaction008.sol b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test2InternalTransaction008.sol new file mode 100644 index 00000000000..f728c2a8bf6 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test2InternalTransaction008.sol @@ -0,0 +1,60 @@ +pragma solidity ^0.4.24; + +contract A{ + constructor() payable public{} + function() payable public{} + + function testAssert(address bAddress,uint256 amount) public payable{ + bAddress.call.value(amount).gas(1000000)(bytes4(keccak256("callCGetZero(bool)")),false);//2.1 + bAddress.call.value(amount).gas(1000000)(bytes4(keccak256("callCGetZero(bool)")),true); + } + function testRequire(address cAddress,uint256 amount) public payable{ + cAddress.call.value(amount).gas(1000000)(bytes4(keccak256("newBAndTransfer(bool)")),false);//2.1 + cAddress.call.value(amount).gas(1000000)(bytes4(keccak256("newBAndTransfer(bool)")),true); + } + function testAssert1(address bAddress,uint256 amount) public payable{ + bAddress.call.value(amount).gas(1000000)(bytes4(keccak256("callCGetZero(bool)")),true); + bAddress.call.value(amount).gas(1000000)(bytes4(keccak256("callCGetZero(bool)")),false);//2.1 + } + function testtRequire2(address cAddress,uint256 amount) public payable{ + cAddress.call.value(amount).gas(1000000)(bytes4(keccak256("newBAndTransfer(bool)")),true); + cAddress.call.value(amount).gas(1000000)(bytes4(keccak256("newBAndTransfer(bool)")),false);//2.1 + } + function getBalance() view public returns(uint256){ + return this.balance; + } +} + +contract B{ + constructor() payable public{} + function() payable public{} + function getOne() payable returns(uint256){ + return 1; + } + function callCGetZero(bool success) payable{ + if(!success){ + assert(1==2); + } + } + function getBalance() view public returns(uint256){ + return this.balance; + } +} + +contract C{ + uint256 public flag=0; + constructor() payable public{} + function() payable public{} + function getZero() payable public returns(uint256){ + return 0; + } + function newBAndTransfer(bool success) payable public returns(uint256){ + flag = 1; + if(!success){ + require(2==1); + } + } + function getFlag() public returns(uint256){ + return flag; + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test3InternalTransaction009.sol b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test3InternalTransaction009.sol new file mode 100644 index 00000000000..199c0884182 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test3InternalTransaction009.sol @@ -0,0 +1,47 @@ +pragma solidity ^0.4.24; + +contract A{ + constructor() payable public{} + function() payable public{} + function test1(address cAddr,address dcontract,address baddress) public payable{ + B b1 = (new B).value(10)();//1.1 + b1.transfer(5);//1.3 + b1.callCGetZero(cAddr, 1);//1.4 + b1.getOne(dcontract,baddress); + } +} + +contract B{ + constructor() payable public{} + function() payable public{} + function getOne(address contractAddres, address toAddress) payable public{ + contractAddres.call(bytes4(keccak256("suicide1(address)")),address(this)); + + } + function callCGetZero(address cAddress,uint256 amount){ + cAddress.call.value(amount)(bytes4(keccak256("getZero()")));//1.5,1.7 + } +} + +contract C{ + constructor() payable public{} + function() payable public{} + function getZero() payable public returns(uint256){ + return 0; + } + function newBAndTransfer() payable public{ + B b1 = (new B).value(7)();//2.2,2.7 + B b2 = (new B).value(3)();//2.4,2.9 + } +} + +contract D{ + constructor () payable public{} + function suicide1(address toAddress) public payable{ + selfdestruct(toAddress); + } + function () payable public{} + function getBalance() public view returns(uint256){ + return this.balance; + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test4InternalTransaction010.sol b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test4InternalTransaction010.sol new file mode 100644 index 00000000000..7c10d407461 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test4InternalTransaction010.sol @@ -0,0 +1,188 @@ +pragma solidity ^0.4.24; + + contract A{ + uint256 public num = 0; + constructor() public payable{} + function transfer() payable public{ + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + + } + function transfer2() payable public{ + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + + } + function getBalance() returns(uint256){ + return this.balance; + } + } + contract B{ + uint256 public num = 0; + function f() payable returns(bool) { + return true; + } + constructor() public payable {} + function payC(address c, bool isRevert) public{ + c.transfer(1);//4 + if (isRevert) { + revert(); + } + } + function getBalance() returns(uint256){ + return this.balance; + } + function () payable{} + } + diff --git a/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test5InternalTransaction012.sol b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test5InternalTransaction012.sol new file mode 100644 index 00000000000..3dd0c1b2cae --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction002test5InternalTransaction012.sol @@ -0,0 +1,51 @@ +pragma solidity ^0.4.24; + +contract A{ + constructor() payable public{} + function() payable public{} + function test1(address bAddr,address eAddr) public payable{ + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + } + +} + +contract B{ + constructor() payable public{} + function() payable public{} + function getOne() payable returns(uint256){ + return 1; + } + function testNN(address eAddress) public payable{ + D d1=(new D).value(1000)(); + d1.getOne(eAddress); + } +} + +contract C{ + constructor() payable public{} + function() payable public{} + function getZero() payable public returns(uint256){ + return 0; + } + function newBAndTransfer() payable public returns(uint256){ + require(2==1); + } +} +contract E{ + constructor() payable public{} + function() payable public{} + function getZero() payable public returns(uint256){ + return 0; + } + function newBAndTransfer() payable public returns(uint256){ + require(2==1); + } +} +contract D{ + constructor() payable public{} + function() payable public{} + function getOne(address eAddress) payable returns(uint256){ + eAddress.call.value(1)(bytes4(keccak256("getZero()")));//2.1 + } + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction013.sol b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction013.sol new file mode 100644 index 00000000000..4e48646270f --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction013.sol @@ -0,0 +1,56 @@ +pragma solidity ^0.4.24; + +contract A{ + constructor() payable public{} + function() payable public{} + function test1(address dAddr) public payable{ + B b1 = (new B).value(10)();//1.1 + b1.testNN(dAddr,2);//1.6 + // C c1 = (new C).value(1000000000000)();//1.2 + // E e1 = (new E).value(1)();//1.2 + } + function test2(address cAddress,uint256 amount) public payable{ + cAddress.call.value(amount)(bytes4(keccak256("newBAndTransfer()")));//2.1 + } +} + +contract B{ + constructor() payable public{} + function() payable public{} + function getOne() payable returns(uint256){ + return 1; + } + function testNN(address dAddress,uint256 amount) public payable{ + // D d1=(new D)(); + dAddress.call.value(amount)(bytes4(keccak256("getOne()")));//2.1 + } +} + +contract C{ + constructor() payable public{} + function() payable public{} + function getZero() payable public returns(uint256){ + return 0; + } + function newBAndTransfer() payable public returns(uint256){ + require(2==1); + } +} +contract E{ + constructor() payable public{} + function() payable public{} + function getZero() payable public returns(uint256){ + return 0; + } + function newBAndTransfer() payable public returns(uint256){ + require(2==1); + } +} +contract D{ + constructor() payable public{} + function() payable public{} + function getOne() payable returns(uint256){ + E e = (new E).value(5)(); + } + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction014.sol b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction014.sol new file mode 100644 index 00000000000..46e1f8e0eed --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction014.sol @@ -0,0 +1,40 @@ +pragma solidity ^0.4.24; + +contract callerContract { + constructor() payable{} + function() payable{} + function sendToB(address called_address,address c) public payable{ + called_address.delegatecall(bytes4(keccak256("transferTo(address)")),c); + } + function sendToB2(address called_address,address c) public payable{ + called_address.call(bytes4(keccak256("transferTo(address)")),c); + } + function sendToB3(address called_address,address c) public payable{ + called_address.callcode(bytes4(keccak256("transferTo(address)")),c); + } +} + + contract calledContract { + function() payable{} + constructor() payable {} + function transferTo(address toAddress)public payable{ + toAddress.transfer(5); + } + + function setIinC(address c) public payable{ + c.call.value(5)(bytes4(keccak256("setI()"))); + } + + } + + contract c{ + uint256 public i=0; + constructor() public payable{} + function getBalance() public view returns(uint256){ + return this.balance; + } + function setI() payable{ + i=5; + } + function() payable{} + } diff --git a/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction015.sol b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction015.sol new file mode 100644 index 00000000000..61666b44892 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction015.sol @@ -0,0 +1,60 @@ +pragma solidity ^0.4.24; + +contract A{ + constructor() payable public{} + function() payable public{} + function test1(address dAddr,address eAddr) public payable{ + B b1 = (new B).value(10)();//1.1 + b1.testNN(dAddr,2,eAddr);//1.6 + // C c1 = (new C).value(1000000000000)();//1.2 + // E e1 = (new E).value(1)();//1.2 + } + function test2(address cAddress,uint256 amount) public payable{ + cAddress.call.value(amount)(bytes4(keccak256("newBAndTransfer()")));//2.1 + } +} + +contract B{ + constructor() payable public{} + function() payable public{} + function getOne() payable returns(uint256){ + return 1; + } + function testNN(address dAddress,uint256 amount,address eAddress) public payable{ + // D d1=(new D)(); + dAddress.call.value(amount)(bytes4(keccak256("getOne(address)")),address(this));//2.1 + } +} + +contract C{ + constructor() payable public{} + function() payable public{} + function getZero() payable public returns(uint256){ + return 0; + } + function newBAndTransfer() payable public returns(uint256){ + require(2==1); + } +} +contract E{ + constructor() payable public{} + function() payable public{} + function getZero() payable public returns(uint256){ + return 0; + } + function newBAndTransfer() payable public returns(uint256){ + require(2==1); + } + function suicide(address toAddress) public payable{ + selfdestruct(toAddress); + } +} +contract D{ + constructor() payable public{} + function() payable public{} + function getOne(address eAddress) payable public{ + E e = (new E).value(5)(); + e.suicide(eAddress); + } + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction016.sol b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction016.sol new file mode 100644 index 00000000000..b0cbe16af4d --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction016.sol @@ -0,0 +1,184 @@ +pragma solidity ^0.4.24; + + contract A{ + uint256 public num = 0; + constructor() public payable{} + function transfer() payable public{ + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + + B b1=(new B).value(1)();//1 + b1.suicide(this); + } + function transfer2() payable public{ + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + B b1=(new B).value(1)();//1 + b1.suicide(this); + } + function getBalance() returns(uint256){ + return this.balance; + } + } + contract B{ + uint256 public num = 0; + function f() payable returns(bool) { + return true; + } + constructor() public payable {} + function payC(address c, bool isRevert) public{ + c.transfer(1);//4 + if (isRevert) { + revert(); + } + } + function getBalance() returns(uint256){ + return this.balance; + } + function () payable{} + function suicide(address toAddress) public payable{ + selfdestruct(toAddress); + } + } + diff --git a/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction017.sol b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction017.sol new file mode 100644 index 00000000000..2352e61b733 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction017.sol @@ -0,0 +1,194 @@ +pragma solidity ^0.4.24; + + contract A{ + uint256 public num = 0; + constructor() public payable{} + function transfer(address Address) payable public{ + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + + B b=(new B).value(1)();//1 + selfdestruct(Address); + } + function transfer2() payable public{ + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + (new B).value(1)();//1 + + } + function getBalance() public returns(uint256){ + return this.balance; + } + } + contract B{ + uint256 public num = 0; + function f() payable returns(bool) { + return true; + } + constructor() public payable {} + function payC(address c, bool isRevert) public{ + c.transfer(1);//4 + if (isRevert) { + revert(); + } + } + function getBalance() returns(uint256){ + return this.balance; + } + function () payable{} + } + diff --git a/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction018.sol b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction018.sol new file mode 100644 index 00000000000..6341ee61b06 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractInternalTransaction003testInternalTransaction018.sol @@ -0,0 +1,149 @@ +pragma solidity ^0.4.24; + +contract A{ + constructor() payable public{} + function() payable public{} + function test1(address bAddr,address eAddr) public payable{ + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + bAddr.call.value(1)(bytes4(keccak256("testNN(address)")),eAddr);//2.1 + + + } + +} + +contract B{ + constructor() payable public{} + function() payable public{} + function getOne() payable returns(uint256){ + return 1; + } + function testNN(address eAddress) public payable{ + D d1=(new D).value(100)(); + d1.getOne(eAddress); + } +} + +contract C{ + constructor() payable public{} + function() payable public{} + function getZero() payable public returns(uint256){ + return 0; + } + function newBAndTransfer() payable public returns(uint256){ + require(2==1); + } +} +contract E{ + constructor() payable public{} + function() payable public{} + function getZero() payable public returns(uint256){ + return 0; + } + function newBAndTransfer() payable public returns(uint256){ + require(2==1); + } +} +contract D{ + constructor() payable public{} + function() payable public{} + function getOne(address eAddress) payable returns(uint256){ + eAddress.call.value(1)(bytes4(keccak256("getZero()")));//2.1 + } + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractLinkage001.sol b/src/test/resources/soliditycode_v0.4.25/contractLinkage001.sol new file mode 100644 index 00000000000..4c04cf5c6fb --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractLinkage001.sol @@ -0,0 +1,9 @@ +//pragma solidity ^0.4.0; + +contract divideIHaveArgsReturnStorage{ +constructor() payable public{} +function() payable external{} +function divideIHaveArgsReturn(int x,int y) public payable returns (int z) { +return z = x / y; +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractLinkage002.sol b/src/test/resources/soliditycode_v0.4.25/contractLinkage002.sol new file mode 100644 index 00000000000..ca38896acee --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractLinkage002.sol @@ -0,0 +1,7 @@ +//pragma solidity ^0.4.0; + +contract divideIHaveArgsReturnStorage{ +function divideIHaveArgsReturn(int x,int y) public returns (int z) { +return z = x / y; +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractLinkage003.sol b/src/test/resources/soliditycode_v0.4.25/contractLinkage003.sol new file mode 100644 index 00000000000..ca38896acee --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractLinkage003.sol @@ -0,0 +1,7 @@ +//pragma solidity ^0.4.0; + +contract divideIHaveArgsReturnStorage{ +function divideIHaveArgsReturn(int x,int y) public returns (int z) { +return z = x / y; +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractLinkage004.sol b/src/test/resources/soliditycode_v0.4.25/contractLinkage004.sol new file mode 100644 index 00000000000..ca38896acee --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractLinkage004.sol @@ -0,0 +1,7 @@ +//pragma solidity ^0.4.0; + +contract divideIHaveArgsReturnStorage{ +function divideIHaveArgsReturn(int x,int y) public returns (int z) { +return z = x / y; +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractLinkage005.sol b/src/test/resources/soliditycode_v0.4.25/contractLinkage005.sol new file mode 100644 index 00000000000..7b943aee5c1 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractLinkage005.sol @@ -0,0 +1,51 @@ +contract timeoutTest { + string public iarray1; + // cpu + function oneCpu() public { + require(1==1); + } + + function storage8Char() public { + iarray1 = "12345678"; + } + + function testUseCpu(uint256 a) public returns (uint256){ + uint256 count = 0; + for (uint256 i = 0; i < a; i++) { + count++; + } + return count; + } + + + uint256[] public iarray; + uint public calculatedFibNumber; + mapping(address=>mapping(address=>uint256)) public m; + + function testUseStorage(uint256 a) public returns (uint256){ + uint256 count = 0; + for (uint256 i = 0; i < a; i++) { + count++; + iarray.push(i); + } + return count; + } + + // stack + //uint n = 0; + uint yy = 0; + function test() public { + //n += 1; + yy += 1; + test(); + } + + function setFibonacci(uint n) public returns (uint256){ + calculatedFibNumber = fibonacci(n); + return calculatedFibNumber; + } + + function fibonacci(uint n) internal returns (uint) { + return fibonacci(n - 1) + fibonacci(n - 2); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractLinkage006.sol b/src/test/resources/soliditycode_v0.4.25/contractLinkage006.sol new file mode 100644 index 00000000000..9b16ff63368 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractLinkage006.sol @@ -0,0 +1,18 @@ +//pragma solidity ^0.4.0; +contract AA{ + uint256 public count=0; + constructor () payable public{} + function init(address addr, uint256 max) payable public { + count =0; + this.hack(addr,max); + } + function hack(address addr, uint256 max) payable public { + while (count < max) { + count = count +1; + this.hack(addr,max); + } + if (count == max) { + addr.send(20); + } + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractOriginEnergyLimit001.sol b/src/test/resources/soliditycode_v0.4.25/contractOriginEnergyLimit001.sol new file mode 100644 index 00000000000..af80b15cc8b --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractOriginEnergyLimit001.sol @@ -0,0 +1,11 @@ +pragma solidity ^0.4.0; + +contract findArgsContractTest{ + function findArgsByIndexTest(uint i) public returns (uint z) { + uint[] memory a = new uint[](3); + a[0]=1; + a[1]=2; + a[2]=3; + return a[i]; + } +} diff --git a/src/test/resources/soliditycode_v0.4.25/contractOriginEnergyLimit004.sol b/src/test/resources/soliditycode_v0.4.25/contractOriginEnergyLimit004.sol new file mode 100644 index 00000000000..af80b15cc8b --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractOriginEnergyLimit004.sol @@ -0,0 +1,11 @@ +pragma solidity ^0.4.0; + +contract findArgsContractTest{ + function findArgsByIndexTest(uint i) public returns (uint z) { + uint[] memory a = new uint[](3); + a[0]=1; + a[1]=2; + a[2]=3; + return a[i]; + } +} diff --git a/src/test/resources/soliditycode_v0.4.25/contractOtherToTrcToken.sol b/src/test/resources/soliditycode_v0.4.25/contractOtherToTrcToken.sol new file mode 100644 index 00000000000..1fcff0c039f --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractOtherToTrcToken.sol @@ -0,0 +1,40 @@ +pragma solidity ^0.4.24; +contract ConvertType { + +constructor() payable public{} + +function() payable external{} + +//function stringToTrctoken(address payable toAddress, string memory tokenStr, uint256 tokenValue) public { +// trcToken t = trcToken(tokenStr); // ERROR +// toAddress.transferToken(tokenValue, tokenStr); // ERROR +//} + +function uint256ToTrctoken(address toAddress,uint256 tokenValue, uint256 tokenInt) public { + trcToken t = trcToken(tokenInt); // OK + toAddress.transferToken(tokenValue, t); // OK + toAddress.transferToken(tokenValue, tokenInt); // OK +} + +function addressToTrctoken(address toAddress, uint256 tokenValue, address adr) public { + trcToken t = trcToken(adr); // OK + toAddress.transferToken(tokenValue, t); // OK +//toAddress.transferToken(tokenValue, adr); // ERROR +} + +//function bytesToTrctoken(address payable toAddress, bytes memory b, uint256 tokenValue) public { + // trcToken t = trcToken(b); // ERROR + // toAddress.transferToken(tokenValue, b); // ERROR +//} + +function bytes32ToTrctoken(address toAddress, uint256 tokenValue, bytes32 b32) public { + trcToken t = trcToken(b32); // OK + toAddress.transferToken(tokenValue, t); // OK +// toAddress.transferToken(tokenValue, b32); // ERROR +} + +//function arrayToTrctoken(address payable toAddress, uint256[] memory arr, uint256 tokenValue) public { +//trcToken t = trcToken(arr); // ERROR +// toAddress.transferToken(tokenValue, arr); // ERROR +//} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractScenario001.sol b/src/test/resources/soliditycode_v0.4.25/contractScenario001.sol new file mode 100644 index 00000000000..ca38896acee --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractScenario001.sol @@ -0,0 +1,7 @@ +//pragma solidity ^0.4.0; + +contract divideIHaveArgsReturnStorage{ +function divideIHaveArgsReturn(int x,int y) public returns (int z) { +return z = x / y; +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractScenario002.sol b/src/test/resources/soliditycode_v0.4.25/contractScenario002.sol new file mode 100644 index 00000000000..c096bbff619 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractScenario002.sol @@ -0,0 +1,53 @@ +//pragma solidity ^0.4.0; +contract TronNative{ + + address public voteContractAddress= address(0x10001); + address public freezeBalanceAddress = address(0x10002); + address public unFreezeBalanceAddress = address(0x10003); + address public withdrawBalanceAddress = address(0x10004); + address public approveProposalAddress = address(0x10005); + address public createProposalAddress = address(0x10006); + address public deleteProposalAddress = address(0x10007); + constructor () payable public {} + + function voteForSingleWitness (address witnessAddr, uint256 voteValue) public{ + // method 1: + voteContractAddress.delegatecall(abi.encode(witnessAddr,voteValue)); + } + + function voteUsingAssembly (address witnessAddr, uint256 voteValue) public{ + // method 2: + assembly{ + mstore(0x80,witnessAddr) + mstore(0xa0,voteValue) + // gas, address, in, size, out, size + if iszero(delegatecall(0, 0x10001, 0x80, 0x40, 0x80, 0x0)) { + revert(0, 0) + } + } + } + + function freezeBalance(uint256 frozen_Balance,uint256 frozen_Duration) public { + freezeBalanceAddress.delegatecall(abi.encode(frozen_Balance,frozen_Duration)); + } + + function unFreezeBalance() public { + unFreezeBalanceAddress.delegatecall(""); + } + + function withdrawBalance() public { + withdrawBalanceAddress.delegatecall(""); + } + + function approveProposal(uint256 id, bool isApprove) public { + approveProposalAddress.delegatecall(abi.encode(id,isApprove)); + } + + function createProposal(bytes32 [] memory data) public { + createProposalAddress.delegatecall(abi.encode(data)); + } + + function deleteProposal(uint256 id) public{ + deleteProposalAddress.delegatecall(abi.encode(id)); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractScenario003.sol b/src/test/resources/soliditycode_v0.4.25/contractScenario003.sol new file mode 100644 index 00000000000..ca38896acee --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractScenario003.sol @@ -0,0 +1,7 @@ +//pragma solidity ^0.4.0; + +contract divideIHaveArgsReturnStorage{ +function divideIHaveArgsReturn(int x,int y) public returns (int z) { +return z = x / y; +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractScenario004.sol b/src/test/resources/soliditycode_v0.4.25/contractScenario004.sol new file mode 100644 index 00000000000..b3ca2687b4c --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractScenario004.sol @@ -0,0 +1,88 @@ +//pragma solidity ^0.4.11; + +contract TronToken { + + string public name = "Tronix"; // token name + string public symbol = "TRX"; // token symbol + uint256 public decimals = 6; // token digit + + mapping (address => uint256) public balanceOf; + mapping (address => mapping (address => uint256)) public allowance; + + uint256 public totalSupply = 0; + bool public stopped = false; + + uint256 constant valueFounder = 100000000000000000; + address owner = address(0x0); + + modifier isOwner { + assert(owner == msg.sender); + _; + } + + modifier isRunning { + assert (!stopped); + _; + } + + modifier validAddress { + assert(address(0x0) != msg.sender); + _; + } + + constructor(address _addressFounder) public { + owner = msg.sender; + totalSupply = valueFounder; + balanceOf[_addressFounder] = valueFounder; + emit Transfer(address(0x0), _addressFounder, valueFounder); + } + + function transfer(address _to, uint256 _value) isRunning validAddress public returns (bool success) { + require(balanceOf[msg.sender] >= _value); + require(balanceOf[_to] + _value >= balanceOf[_to]); + balanceOf[msg.sender] -= _value; + balanceOf[_to] += _value; + emit Transfer(msg.sender, _to, _value); + return true; + } + + function transferFrom(address _from, address _to, uint256 _value) isRunning validAddress public returns (bool success) { + require(balanceOf[_from] >= _value); + require(balanceOf[_to] + _value >= balanceOf[_to]); + require(allowance[_from][msg.sender] >= _value); + balanceOf[_to] += _value; + balanceOf[_from] -= _value; + allowance[_from][msg.sender] -= _value; + emit Transfer(_from, _to, _value); + return true; + } + + function approve(address _spender, uint256 _value) isRunning validAddress public returns (bool success) { + require(_value == 0 || allowance[msg.sender][_spender] == 0); + allowance[msg.sender][_spender] = _value; + emit Approval(msg.sender, _spender, _value); + return true; + } + + function stop() isOwner public { + stopped = true; + } + + function start() isOwner public { + stopped = false; + } + + function setName(string memory _name) isOwner public { + name = _name; + } + + function burn(uint256 _value) public { + require(balanceOf[msg.sender] >= _value); + balanceOf[msg.sender] -= _value; + balanceOf[address(0x0)] += _value; + emit Transfer(msg.sender, address(0x0), _value); + } + + event Transfer(address indexed _from, address indexed _to, uint256 _value); + event Approval(address indexed _owner, address indexed _spender, uint256 _value); +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractScenario005.sol b/src/test/resources/soliditycode_v0.4.25/contractScenario005.sol new file mode 100644 index 00000000000..f4bec71761c --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractScenario005.sol @@ -0,0 +1,103 @@ +//pragma solidity ^0.4.16; + +interface token { + function transfer(address receiver, uint amount); +} + +contract Crowdsale { + address public beneficiary = 0x1B228F5D9F934C7BB18AAA86F90418932888E7B4; // 募资成功后的收款方 + uint public fundingGoal = 10000000; // 募资额度 + uint public amountRaised = 1000000; // 参与数量 + uint public deadline; // 募资截止期 + + uint public price; // token 与以太坊的汇率 , token卖多少钱 + token public tokenReward; // 要卖的token + + mapping(address => uint256) public balanceOf; + + bool fundingGoalReached = false; // 众筹是否达到目标 + bool crowdsaleClosed = false; // 众筹是否结束 + + /** + * 事件可以用来跟踪信息 + **/ + event GoalReached(address recipient, uint totalAmountRaised); + event FundTransfer(address backer, uint amount, bool isContribution); + + /** + * 构造函数, 设置相关属性 + */ + function Crowdsale( + address ifSuccessfulSendTo, + uint fundingGoalInEthers, + uint durationInMinutes, + uint finneyCostOfEachToken, + address addressOfTokenUsedAsReward) { + beneficiary = ifSuccessfulSendTo; + fundingGoal = fundingGoalInEthers * 1 sun; + deadline = now + durationInMinutes * 1 minutes; + price = finneyCostOfEachToken * 1 sun; + tokenReward = token(addressOfTokenUsedAsReward); // 传入已发布的 token 合约的地址来创建实例 + } + + /** + * 无函数名的Fallback函数, + * 在向合约转账时,这个函数会被调用 + */ + function () payable { + require(!crowdsaleClosed); + uint amount = msg.value; + balanceOf[msg.sender] += amount; + amountRaised += amount; + tokenReward.transfer(msg.sender, amount / price); + FundTransfer(msg.sender, amount, true); + } + + /** + * 定义函数修改器modifier(作用和Python的装饰器很相似) + * 用于在函数执行前检查某种前置条件(判断通过之后才会继续执行该方法) + * _ 表示继续执行之后的代码 + **/ + modifier afterDeadline() { if (now >= deadline) _; } + + /** + * 判断众筹是否完成融资目标, 这个方法使用了afterDeadline函数修改器 + * + */ + function checkGoalReached() afterDeadline { + if (amountRaised >= fundingGoal) { + fundingGoalReached = true; + GoalReached(beneficiary, amountRaised); + } + crowdsaleClosed = true; + } + + + /** + * 完成融资目标时,融资款发送到收款方 + * 未完成融资目标时,执行退款 + * + */ + function safeWithdrawal() afterDeadline { + if (!fundingGoalReached) { + uint amount = balanceOf[msg.sender]; + balanceOf[msg.sender] = 0; + if (amount > 0) { + if (msg.sender.send(amount)) { + FundTransfer(msg.sender, amount, false); + } else { + balanceOf[msg.sender] = amount; + } + } + } + + if (fundingGoalReached && beneficiary == msg.sender) { + if (beneficiary.send(amountRaised)) { + FundTransfer(beneficiary, amountRaised, false); + } else { + //If we fail to send the funds to beneficiary, unlock funders balance + fundingGoalReached = false; + } + } + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractScenario006.sol b/src/test/resources/soliditycode_v0.4.25/contractScenario006.sol new file mode 100644 index 00000000000..af55371cb6e --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractScenario006.sol @@ -0,0 +1,1954 @@ +//pragma solidity ^0.4.24; + +interface PlayerBookInterface { + function getPlayerID(address _addr) external returns (uint256); + function getPlayerName(uint256 _pID) external view returns (bytes32); + function getPlayerLAff(uint256 _pID) external view returns (uint256); + function getPlayerAddr(uint256 _pID) external view returns (address); + function getNameFee() external view returns (uint256); + function registerNameXIDFromDapp(address _addr, bytes32 _name, uint256 _affCode, bool _all) external payable returns(bool, uint256); + function registerNameXaddrFromDapp(address _addr, bytes32 _name, address _affCode, bool _all) external payable returns(bool, uint256); + function registerNameXnameFromDapp(address _addr, bytes32 _name, bytes32 _affCode, bool _all) external payable returns(bool, uint256); + function isDev(address _who) external view returns(bool); +} + + +/** +* @title -Name Filter- v0.1.9 +* ┌┬┐┌─┐┌─┐┌┬┐ ╦╦ ╦╔═╗╔╦╗ ┌─┐┬─┐┌─┐┌─┐┌─┐┌┐┌┌┬┐┌─┐ +* │ ├┤ ├─┤│││ ║║ ║╚═╗ ║ ├─┘├┬┘├┤ └─┐├┤ │││ │ └─┐ +* ┴ └─┘┴ ┴┴ ┴ ╚╝╚═╝╚═╝ ╩ ┴ ┴└─└─┘└─┘└─┘┘└┘ ┴ └─┘ +* _____ _____ +* (, / /) /) /) (, / /) /) +* ┌─┐ / _ (/_ // // / _ // _ __ _(/ +* ├─┤ ___/___(/_/(__(_/_(/_(/_ ___/__/_)_(/_(_(_/ (_(_(_ +* ┴ ┴ / / .-/ _____ (__ / +* (__ / (_/ (, / /)™ +* / __ __ __ __ _ __ __ _ _/_ _ _(/ +* ┌─┐┬─┐┌─┐┌┬┐┬ ┬┌─┐┌┬┐ /__/ (_(__(_)/ (_/_)_(_)/ (_(_(_(__(/_(_(_ +* ├─┘├┬┘│ │ │││ ││ │ (__ / .-/ © Jekyll Island Inc. 2018 +* ┴ ┴└─└─┘─┴┘└─┘└─┘ ┴ (_/ +* _ __ _ ____ ____ _ _ _____ ____ ___ +*=============| |\ | / /\ | |\/| | |_ =====| |_ | | | | | | | |_ | |_)==============* +*=============|_| \| /_/--\ |_| | |_|__=====|_| |_| |_|__ |_| |_|__ |_| \==============* +* +* ╔═╗┌─┐┌┐┌┌┬┐┬─┐┌─┐┌─┐┌┬┐ ╔═╗┌─┐┌┬┐┌─┐ ┌──────────┐ +* ║ │ ││││ │ ├┬┘├─┤│ │ ║ │ │ ││├┤ │ Inventor │ +* ╚═╝└─┘┘└┘ ┴ ┴└─┴ ┴└─┘ ┴ ╚═╝└─┘─┴┘└─┘ └──────────┘ +*/ + +library NameFilter { + /** + * @dev filters name strings + * -converts uppercase to lower case. + * -makes sure it does not start/end with a space + * -makes sure it does not contain multiple spaces in a row + * -cannot be only numbers + * -cannot start with 0x + * -restricts characters to A-Z, a-z, 0-9, and space. + * @return reprocessed string in bytes32 format + */ + function nameFilter(string _input) + internal + pure + returns(bytes32) + { + bytes memory _temp = bytes(_input); + uint256 _length = _temp.length; + + //sorry limited to 32 characters + require (_length <= 32 && _length > 0, "string must be between 1 and 32 characters"); + // make sure it doesnt start with or end with space + require(_temp[0] != 0x20 && _temp[_length-1] != 0x20, "string cannot start or end with space"); + // make sure first two characters are not 0x + if (_temp[0] == 0x30) + { + require(_temp[1] != 0x78, "string cannot start with 0x"); + require(_temp[1] != 0x58, "string cannot start with 0X"); + } + + // create a bool to track if we have a non number character + bool _hasNonNumber; + + // convert & check + for (uint256 i = 0; i < _length; i++) + { + // if its uppercase A-Z + if (_temp[i] > 0x40 && _temp[i] < 0x5b) + { + // convert to lower case a-z + _temp[i] = byte(uint(_temp[i]) + 32); + + // we have a non number + if (_hasNonNumber == false) + _hasNonNumber = true; + } else { + require + ( + // require character is a space + _temp[i] == 0x20 || + // OR lowercase a-z + (_temp[i] > 0x60 && _temp[i] < 0x7b) || + // or 0-9 + (_temp[i] > 0x2f && _temp[i] < 0x3a), + "string contains invalid characters" + ); + // make sure theres not 2x spaces in a row + if (_temp[i] == 0x20) + require( _temp[i+1] != 0x20, "string cannot contain consecutive spaces"); + + // see if we have a character other than a number + if (_hasNonNumber == false && (_temp[i] < 0x30 || _temp[i] > 0x39)) + _hasNonNumber = true; + } + } + + require(_hasNonNumber == true, "string cannot be only numbers"); + + bytes32 _ret; + assembly { + _ret := mload(add(_temp, 32)) + } + return (_ret); + } +} + + +library SafeMath { + + /** + * @dev Multiplies two numbers, throws on overflow. + */ + function mul(uint256 a, uint256 b) + internal + pure + returns (uint256 c) + { + if (a == 0) { + return 0; + } + c = a * b; + require(c / a == b, "SafeMath mul failed"); + return c; + } + + /** + * @dev Integer division of two numbers, truncating the quotient. + */ + function div(uint256 a, uint256 b) internal pure returns (uint256) { + // assert(b > 0); // Solidity automatically throws when dividing by 0 + uint256 c = a / b; + // assert(a == b * c + a % b); // There is no case in which this doesn't hold + return c; + } + + /** + * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). + */ + function sub(uint256 a, uint256 b) + internal + pure + returns (uint256) + { + require(b <= a, "SafeMath sub failed"); + return a - b; + } + + /** + * @dev Adds two numbers, throws on overflow. + */ + function add(uint256 a, uint256 b) + internal + pure + returns (uint256 c) + { + c = a + b; + require(c >= a, "SafeMath add failed"); + return c; + } + + /** + * @dev gives square root of given x. + */ + function sqrt(uint256 x) + internal + pure + returns (uint256 y) + { + uint256 z = ((add(x,1)) / 2); + y = x; + while (z < y) + { + y = z; + z = ((add((x / z),z)) / 2); + } + } + + /** + * @dev gives square. multiplies x by x + */ + function sq(uint256 x) + internal + pure + returns (uint256) + { + return (mul(x,x)); + } + + /** + * @dev x to the power of y + */ + function pwr(uint256 x, uint256 y) + internal + pure + returns (uint256) + { + if (x==0) + return (0); + else if (y==0) + return (1); + else + { + uint256 z = x; + for (uint256 i=1; i < y; i++) + z = mul(z,x); + return (z); + } + } +} + +//============================================================================== +// | _ _ _ | _ . +// |<(/_\/ (_(_||(_ . +//=======/====================================================================== +library F3DKeysCalcLong { + using SafeMath for *; + /** + * @dev calculates number of keys received given X eth + * @param _curEth current amount of eth in contract + * @param _newEth eth being spent + * @return amount of ticket purchased + */ + function keysRec(uint256 _curEth, uint256 _newEth) + internal + pure + returns (uint256) + { + return(keys((_curEth).add(_newEth)).sub(keys(_curEth))); + } + + /** + * @dev calculates amount of eth received if you sold X keys + * @param _curKeys current amount of keys that exist + * @param _sellKeys amount of keys you wish to sell + * @return amount of eth received + */ + function ethRec(uint256 _curKeys, uint256 _sellKeys) + internal + pure + returns (uint256) + { + return((eth(_curKeys)).sub(eth(_curKeys.sub(_sellKeys)))); + } + + /** + * @dev calculates how many keys would exist with given an amount of eth + * @param _eth eth "in contract" + * @return number of keys that would exist + */ + function keys(uint256 _eth) + internal + pure + returns(uint256) + { + return ((((((_eth).mul(1000000000000000000)).mul(312500000000000000000000000)).add(5624988281256103515625000000000000000000000000000000000000000000)).sqrt()).sub(74999921875000000000000000000000)) / (156250000); + } + + /** + * @dev calculates how much eth would be in contract given a number of keys + * @param _keys number of keys "in contract" + * @return eth that would exists + */ + function eth(uint256 _keys) + internal + pure + returns(uint256) + { + return ((78125000).mul(_keys.sq()).add(((149999843750000).mul(_keys.mul(1000000000000000000))) / (2))) / ((1000000000000000000).sq()); + } +} + +library F3Ddatasets { + //compressedData key + // [76-33][32][31][30][29][28-18][17][16-6][5-3][2][1][0] + // 0 - new player (bool) + // 1 - joined round (bool) + // 2 - new leader (bool) + // 3-5 - air drop tracker (uint 0-999) + // 6-16 - round end time + // 17 - winnerTeam + // 18 - 28 timestamp + // 29 - team + // 30 - 0 = reinvest (round), 1 = buy (round), 2 = buy (ico), 3 = reinvest (ico) + // 31 - airdrop happened bool + // 32 - airdrop tier + // 33 - airdrop amount won + //compressedIDs key + // [77-52][51-26][25-0] + // 0-25 - pID + // 26-51 - winPID + // 52-77 - rID + struct EventReturns { + uint256 compressedData; + uint256 compressedIDs; + address winnerAddr; // winner address + bytes32 winnerName; // winner name + uint256 amountWon; // amount won + uint256 newPot; // amount in new pot + uint256 P3DAmount; // amount distributed to p3d + uint256 genAmount; // amount distributed to gen + uint256 potAmount; // amount added to pot + } + struct Player { + address addr; // player address + bytes32 name; // player name + uint256 win; // winnings vault + uint256 gen; // general vault + uint256 aff; // affiliate vault + uint256 lrnd; // last round played + uint256 laff; // last affiliate id used + } + struct PlayerRounds { + uint256 eth; // eth player has added to round (used for eth limiter) + uint256 keys; // keys + uint256 mask; // player mask + uint256 ico; // ICO phase investment + } + struct Round { + uint256 plyr; // pID of player in lead + uint256 team; // tID of team in lead + uint256 end; // time ends/ended + bool ended; // has round end function been ran + uint256 strt; // time round started + uint256 keys; // keys + uint256 eth; // total eth in + uint256 pot; // eth to pot (during round) / final amount paid to winner (after round ends) + uint256 mask; // global mask + uint256 ico; // total eth sent in during ICO phase + uint256 icoGen; // total eth for gen during ICO phase + uint256 icoAvg; // average key price for ICO phase + } + struct TeamFee { + uint256 gen; // % of buy in thats paid to key holders of current round + uint256 p3d; // % of buy in thats paid to p3d holders + } + struct PotSplit { + uint256 gen; // % of pot thats paid to key holders of current round + uint256 p3d; // % of pot thats paid to p3d holders + } +} + +contract F3Devents { + // fired whenever a player registers a name + event onNewName + ( + uint256 indexed playerID, + address indexed playerAddress, + bytes32 indexed playerName, + bool isNewPlayer, + uint256 affiliateID, + address affiliateAddress, + bytes32 affiliateName, + uint256 amountPaid, + uint256 timeStamp + ); + + // fired at end of buy or reload + event onEndTx + ( + uint256 compressedData, + uint256 compressedIDs, + bytes32 playerName, + address playerAddress, + uint256 ethIn, + uint256 keysBought, + address winnerAddr, + bytes32 winnerName, + uint256 amountWon, + uint256 newPot, + uint256 P3DAmount, + uint256 genAmount, + uint256 potAmount, + uint256 airDropPot + ); + + // fired whenever theres a withdraw + event onWithdraw + ( + uint256 indexed playerID, + address playerAddress, + bytes32 playerName, + uint256 ethOut, + uint256 timeStamp + ); + + // fired whenever a withdraw forces end round to be ran + event onWithdrawAndDistribute + ( + address playerAddress, + bytes32 playerName, + uint256 ethOut, + uint256 compressedData, + uint256 compressedIDs, + address winnerAddr, + bytes32 winnerName, + uint256 amountWon, + uint256 newPot, + uint256 P3DAmount, + uint256 genAmount + ); + + // (fomo3d long only) fired whenever a player tries a buy after round timer + // hit zero, and causes end round to be ran. + event onBuyAndDistribute + ( + address playerAddress, + bytes32 playerName, + uint256 ethIn, + uint256 compressedData, + uint256 compressedIDs, + address winnerAddr, + bytes32 winnerName, + uint256 amountWon, + uint256 newPot, + uint256 P3DAmount, + uint256 genAmount + ); + + // (fomo3d long only) fired whenever a player tries a reload after round timer + // hit zero, and causes end round to be ran. + event onReLoadAndDistribute + ( + address playerAddress, + bytes32 playerName, + uint256 compressedData, + uint256 compressedIDs, + address winnerAddr, + bytes32 winnerName, + uint256 amountWon, + uint256 newPot, + uint256 P3DAmount, + uint256 genAmount + ); + + // fired whenever an affiliate is paid + event onAffiliatePayout + ( + uint256 indexed affiliateID, + address affiliateAddress, + bytes32 affiliateName, + uint256 indexed roundID, + uint256 indexed buyerID, + uint256 amount, + uint256 timeStamp + ); + + // received pot swap deposit + event onPotSwapDeposit + ( + uint256 roundID, + uint256 amountAddedToPot + ); +} + + + +contract FoMo3Dlong is F3Devents { + using SafeMath for *; + using NameFilter for string; + using F3DKeysCalcLong for uint256; + + address public otherF3D_; + address public Divies; + address public Jekyll_Island_Inc; + PlayerBookInterface public playerBook;// =PlayerBookInterface(0x0dcd2f752394c41875e259e00bb44fd505297caf);//new PlayerBook();// + // TeamJustInterface constant private teamJust = TeamJustInterface(0x3a5f8140b9213a0f733a6a639857c9df43ee3f5a);// new TeamJust();// + + //============================================================================== + // _ _ _ |`. _ _ _ |_ | _ _ . + // (_(_)| |~|~|(_||_|| (_||_)|(/__\ . (game settings) + //=================_|=========================================================== + string constant public name = "FoMo3D Long Official"; + string constant public symbol = "F3D"; + uint256 private rndExtra_ = 30;//extSettings.getLongExtra(); // length of the very first ICO + uint256 private rndGap_ = 30; //extSettings.getLongGap(); // length of ICO phase, set to 1 year for EOS. + uint256 constant private rndInit_ = 1 hours; // round timer starts at this + uint256 constant private rndInc_ = 30 seconds; // every full key purchased adds this much to the timer + uint256 constant private rndMax_ = 24 hours; // max length a round timer can be + //============================================================================== + // _| _ _|_ _ _ _ _|_ _ . + // (_|(_| | (_| _\(/_ | |_||_) . (data used to store game info that changes) + //=============================|================================================ + uint256 public airDropPot_; // person who gets the airdrop wins part of this pot + uint256 public airDropTracker_ = 0; // incremented each time a "qualified" tx occurs. used to determine winning air drop + uint256 public rID_; // round id number / total rounds that have happened + //**************** + // PLAYER DATA + //**************** + mapping(address => uint256) public pIDxAddr_; // (addr => pID) returns player id by address + mapping(bytes32 => uint256) public pIDxName_; // (name => pID) returns player id by name + mapping(uint256 => F3Ddatasets.Player) public plyr_; // (pID => data) player data + mapping(uint256 => mapping(uint256 => F3Ddatasets.PlayerRounds)) public plyrRnds_; // (pID => rID => data) player round data by player id & round id + mapping(uint256 => mapping(bytes32 => bool)) public plyrNames_; // (pID => name => bool) list of names a player owns. (used so you can change your display name amongst any name you own) + //**************** + // ROUND DATA + //**************** + mapping(uint256 => F3Ddatasets.Round) public round_; // (rID => data) round data + mapping(uint256 => mapping(uint256 => uint256)) public rndTmEth_; // (rID => tID => data) eth in per team, by round id and team id + //**************** + // TEAM FEE DATA + //**************** + mapping(uint256 => F3Ddatasets.TeamFee) public fees_; // (team => fees) fee distribution by team + mapping(uint256 => F3Ddatasets.PotSplit) public potSplit_; // (team => fees) pot split distribution by team + + function setPlayerBook(address _playerBook) external { + require(msg.sender == owner, 'only dev!'); + require(address(playerBook) == address(0), 'already set!'); + playerBook = PlayerBookInterface(_playerBook); + } + + address public owner; + + //============================================================================== + // _ _ _ __|_ _ __|_ _ _ . + // (_(_)| |_\ | | |_|(_ | (_)| . (initial data setup upon contract deploy) + //============================================================================== + constructor() + public + { + owner = msg.sender; + // Team allocation structures + // 0 = whales + // 1 = bears + // 2 = sneks + // 3 = bulls + + // Team allocation percentages + // (F3D, P3D) + (Pot , Referrals, Community) + // Referrals / Community rewards are mathematically designed to come from the winner's share of the pot. + fees_[0] = F3Ddatasets.TeamFee(30, 6); + //50% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot + fees_[1] = F3Ddatasets.TeamFee(43, 0); + //43% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot + fees_[2] = F3Ddatasets.TeamFee(56, 10); + //20% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot + fees_[3] = F3Ddatasets.TeamFee(43, 8); + //35% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot + + // how to split up the final pot based on which team was picked + // (F3D, P3D) + potSplit_[0] = F3Ddatasets.PotSplit(15, 10); + //48% to winner, 25% to next round, 2% to com + potSplit_[1] = F3Ddatasets.PotSplit(25, 0); + //48% to winner, 25% to next round, 2% to com + potSplit_[2] = F3Ddatasets.PotSplit(20, 20); + //48% to winner, 10% to next round, 2% to com + potSplit_[3] = F3Ddatasets.PotSplit(30, 10); + //48% to winner, 10% to next round, 2% to com + } + //============================================================================== + // _ _ _ _|. |`. _ _ _ . + // | | |(_)(_||~|~|(/_| _\ . (these are safety checks) + //============================================================================== + /** + * @dev used to make sure no one can interact with contract until it has + * been activated. + */ + modifier isActivated() { + require(activated_ == true, "its not ready yet. check ?eta in discord"); + _; + } + + /** + * @dev prevents contracts from interacting with fomo3d + */ + modifier isHuman() { + address _addr = msg.sender; + uint256 _codeLength; + + assembly {_codeLength := extcodesize(_addr)} + require(_codeLength == 0, "sorry humans only"); + _; + } + + modifier onlyDevs() + { + require(playerBook.isDev(msg.sender) == true, "msg sender is not a dev"); + _; + } + + /** + * @dev sets boundaries for incoming tx + */ + modifier isWithinLimits(uint256 _eth) { + require(_eth >= 1000000000, "pocket lint: not a valid currency"); + require(_eth <= 100000000000000000000000, "no vitalik, no"); + _; + } + + //============================================================================== + // _ |_ |. _ |` _ __|_. _ _ _ . + // |_)|_||_)||(_ ~|~|_|| |(_ | |(_)| |_\ . (use these to interact with contract) + //====|========================================================================= + /** + * @dev emergency buy uses last stored affiliate ID and team snek + */ + function() + isActivated() + isHuman() + isWithinLimits(msg.value) + public + payable + { + // set up our tx event data and determine if player is new or not + F3Ddatasets.EventReturns memory _eventData_ = determinePID(_eventData_); + + // fetch player id + uint256 _pID = pIDxAddr_[msg.sender]; + + // buy core + buyCore(_pID, plyr_[_pID].laff, 2, _eventData_); + } + + /** + * @dev converts all incoming ethereum to keys. + * -functionhash- 0x8f38f309 (using ID for affiliate) + * -functionhash- 0x98a0871d (using address for affiliate) + * -functionhash- 0xa65b37a1 (using name for affiliate) + * @param _affCode the ID/address/name of the player who gets the affiliate fee + * @param _team what team is the player playing for? + */ + function buyXid(uint256 _affCode, uint256 _team) + isActivated() + isHuman() + isWithinLimits(msg.value) + public + payable + { + // set up our tx event data and determine if player is new or not + F3Ddatasets.EventReturns memory _eventData_ = determinePID(_eventData_); + + // fetch player id + uint256 _pID = pIDxAddr_[msg.sender]; + + // manage affiliate residuals + // if no affiliate code was given or player tried to use their own, lolz + if (_affCode == 0 || _affCode == _pID) + { + // use last stored affiliate code + _affCode = plyr_[_pID].laff; + + // if affiliate code was given & its not the same as previously stored + } else if (_affCode != plyr_[_pID].laff) { + // update last affiliate + plyr_[_pID].laff = _affCode; + } + + // verify a valid team was selected + _team = verifyTeam(_team); + + // buy core + buyCore(_pID, _affCode, _team, _eventData_); + } + + function buyXaddr(address _affCode, uint256 _team) + isActivated() + isHuman() + isWithinLimits(msg.value) + public + payable + { + // set up our tx event data and determine if player is new or not + F3Ddatasets.EventReturns memory _eventData_ = determinePID(_eventData_); + + // fetch player id + uint256 _pID = pIDxAddr_[msg.sender]; + + // manage affiliate residuals + uint256 _affID; + // if no affiliate code was given or player tried to use their own, lolz + if (_affCode == address(0) || _affCode == msg.sender) + { + // use last stored affiliate code + _affID = plyr_[_pID].laff; + + // if affiliate code was given + } else { + // get affiliate ID from aff Code + _affID = pIDxAddr_[_affCode]; + + // if affID is not the same as previously stored + if (_affID != plyr_[_pID].laff) + { + // update last affiliate + plyr_[_pID].laff = _affID; + } + } + + // verify a valid team was selected + _team = verifyTeam(_team); + + // buy core + buyCore(_pID, _affID, _team, _eventData_); + } + + function buyXname(bytes32 _affCode, uint256 _team) + isActivated() + isHuman() + isWithinLimits(msg.value) + public + payable + { + // set up our tx event data and determine if player is new or not + F3Ddatasets.EventReturns memory _eventData_ = determinePID(_eventData_); + + // fetch player id + uint256 _pID = pIDxAddr_[msg.sender]; + + // manage affiliate residuals + uint256 _affID; + // if no affiliate code was given or player tried to use their own, lolz + if (_affCode == '' || _affCode == plyr_[_pID].name) + { + // use last stored affiliate code + _affID = plyr_[_pID].laff; + + // if affiliate code was given + } else { + // get affiliate ID from aff Code + _affID = pIDxName_[_affCode]; + + // if affID is not the same as previously stored + if (_affID != plyr_[_pID].laff) + { + // update last affiliate + plyr_[_pID].laff = _affID; + } + } + + // verify a valid team was selected + _team = verifyTeam(_team); + + // buy core + buyCore(_pID, _affID, _team, _eventData_); + } + + /** + * @dev essentially the same as buy, but instead of you sending ether + * from your wallet, it uses your unwithdrawn earnings. + * -functionhash- 0x349cdcac (using ID for affiliate) + * -functionhash- 0x82bfc739 (using address for affiliate) + * -functionhash- 0x079ce327 (using name for affiliate) + * @param _affCode the ID/address/name of the player who gets the affiliate fee + * @param _team what team is the player playing for? + * @param _eth amount of earnings to use (remainder returned to gen vault) + */ + function reLoadXid(uint256 _affCode, uint256 _team, uint256 _eth) + isActivated() + isHuman() + isWithinLimits(_eth) + public + { + // set up our tx event data + F3Ddatasets.EventReturns memory _eventData_; + + // fetch player ID + uint256 _pID = pIDxAddr_[msg.sender]; + + // manage affiliate residuals + // if no affiliate code was given or player tried to use their own, lolz + if (_affCode == 0 || _affCode == _pID) + { + // use last stored affiliate code + _affCode = plyr_[_pID].laff; + + // if affiliate code was given & its not the same as previously stored + } else if (_affCode != plyr_[_pID].laff) { + // update last affiliate + plyr_[_pID].laff = _affCode; + } + + // verify a valid team was selected + _team = verifyTeam(_team); + + // reload core + reLoadCore(_pID, _affCode, _team, _eth, _eventData_); + } + + function reLoadXaddr(address _affCode, uint256 _team, uint256 _eth) + isActivated() + isHuman() + isWithinLimits(_eth) + public + { + // set up our tx event data + F3Ddatasets.EventReturns memory _eventData_; + + // fetch player ID + uint256 _pID = pIDxAddr_[msg.sender]; + + // manage affiliate residuals + uint256 _affID; + // if no affiliate code was given or player tried to use their own, lolz + if (_affCode == address(0) || _affCode == msg.sender) + { + // use last stored affiliate code + _affID = plyr_[_pID].laff; + + // if affiliate code was given + } else { + // get affiliate ID from aff Code + _affID = pIDxAddr_[_affCode]; + + // if affID is not the same as previously stored + if (_affID != plyr_[_pID].laff) + { + // update last affiliate + plyr_[_pID].laff = _affID; + } + } + + // verify a valid team was selected + _team = verifyTeam(_team); + + // reload core + reLoadCore(_pID, _affID, _team, _eth, _eventData_); + } + + function reLoadXname(bytes32 _affCode, uint256 _team, uint256 _eth) + isActivated() + isHuman() + isWithinLimits(_eth) + public + { + // set up our tx event data + F3Ddatasets.EventReturns memory _eventData_; + + // fetch player ID + uint256 _pID = pIDxAddr_[msg.sender]; + + // manage affiliate residuals + uint256 _affID; + // if no affiliate code was given or player tried to use their own, lolz + if (_affCode == '' || _affCode == plyr_[_pID].name) + { + // use last stored affiliate code + _affID = plyr_[_pID].laff; + + // if affiliate code was given + } else { + // get affiliate ID from aff Code + _affID = pIDxName_[_affCode]; + + // if affID is not the same as previously stored + if (_affID != plyr_[_pID].laff) + { + // update last affiliate + plyr_[_pID].laff = _affID; + } + } + + // verify a valid team was selected + _team = verifyTeam(_team); + + // reload core + reLoadCore(_pID, _affID, _team, _eth, _eventData_); + } + + /** + * @dev withdraws all of your earnings. + * -functionhash- 0x3ccfd60b + */ + function withdraw() + isActivated() + isHuman() + public + { + // setup local rID + uint256 _rID = rID_; + + // grab time + uint256 _now = now; + + // fetch player ID + uint256 _pID = pIDxAddr_[msg.sender]; + + // setup temp var for player eth + uint256 _eth; + + // check to see if round has ended and no one has run round end yet + if (_now > round_[_rID].end && round_[_rID].ended == false && round_[_rID].plyr != 0) + { + // set up our tx event data + F3Ddatasets.EventReturns memory _eventData_; + + // end the round (distributes pot) + round_[_rID].ended = true; + _eventData_ = endRound(_eventData_); + + // get their earnings + _eth = withdrawEarnings(_pID); + + // gib moni + if (_eth > 0) + plyr_[_pID].addr.transfer(_eth); + + // build event data + _eventData_.compressedData = _eventData_.compressedData + (_now * 1000000000000000000); + _eventData_.compressedIDs = _eventData_.compressedIDs + _pID; + + // fire withdraw and distribute event + emit F3Devents.onWithdrawAndDistribute + ( + msg.sender, + plyr_[_pID].name, + _eth, + _eventData_.compressedData, + _eventData_.compressedIDs, + _eventData_.winnerAddr, + _eventData_.winnerName, + _eventData_.amountWon, + _eventData_.newPot, + _eventData_.P3DAmount, + _eventData_.genAmount + ); + + // in any other situation + } else { + // get their earnings + _eth = withdrawEarnings(_pID); + + // gib moni + if (_eth > 0) + plyr_[_pID].addr.transfer(_eth); + + // fire withdraw event + emit F3Devents.onWithdraw(_pID, msg.sender, plyr_[_pID].name, _eth, _now); + } + } + + /** + * @dev use these to register names. they are just wrappers that will send the + * registration requests to the PlayerBook contract. So registering here is the + * same as registering there. UI will always display the last name you registered. + * but you will still own all previously registered names to use as affiliate + * links. + * - must pay a registration fee. + * - name must be unique + * - names will be converted to lowercase + * - name cannot start or end with a space + * - cannot have more than 1 space in a row + * - cannot be only numbers + * - cannot start with 0x + * - name must be at least 1 char + * - max length of 32 characters long + * - allowed characters: a-z, 0-9, and space + * -functionhash- 0x921dec21 (using ID for affiliate) + * -functionhash- 0x3ddd4698 (using address for affiliate) + * -functionhash- 0x685ffd83 (using name for affiliate) + * @param _nameString players desired name + * @param _affCode affiliate ID, address, or name of who referred you + * @param _all set to true if you want this to push your info to all games + * (this might cost a lot of gas) + */ + function registerNameXID(string _nameString, uint256 _affCode, bool _all) + isHuman() + public + payable + { + bytes32 _name = _nameString.nameFilter(); + address _addr = msg.sender; + uint256 _paid = msg.value; + (bool _isNewPlayer, uint256 _affID) = playerBook.registerNameXIDFromDapp.value(_paid)(_addr, _name, _affCode, _all); + + uint256 _pID = pIDxAddr_[_addr]; + + // fire event + emit F3Devents.onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, _paid, now); + } + + function registerNameXaddr(string _nameString, address _affCode, bool _all) + isHuman() + public + payable + { + bytes32 _name = _nameString.nameFilter(); + address _addr = msg.sender; + uint256 _paid = msg.value; + (bool _isNewPlayer, uint256 _affID) = playerBook.registerNameXaddrFromDapp.value(msg.value)(msg.sender, _name, _affCode, _all); + + uint256 _pID = pIDxAddr_[_addr]; + + // fire event + emit F3Devents.onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, _paid, now); + } + + function registerNameXname(string _nameString, bytes32 _affCode, bool _all) + isHuman() + public + payable + { + bytes32 _name = _nameString.nameFilter(); + address _addr = msg.sender; + uint256 _paid = msg.value; + (bool _isNewPlayer, uint256 _affID) = playerBook.registerNameXnameFromDapp.value(msg.value)(msg.sender, _name, _affCode, _all); + + uint256 _pID = pIDxAddr_[_addr]; + + // fire event + emit F3Devents.onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, _paid, now); + } + //============================================================================== + // _ _ _|__|_ _ _ _ . + // (_|(/_ | | (/_| _\ . (for UI & viewing things on etherscan) + //=====_|======================================================================= + /** + * @dev return the price buyer will pay for next 1 individual key. + * -functionhash- 0x018a25e8 + * @return price for next key bought (in wei format) + */ + function getBuyPrice() + public + view + returns (uint256) + { + // setup local rID + uint256 _rID = rID_; + + // grab time + uint256 _now = now; + + // are we in a round? + if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) + return ((round_[_rID].keys.add(1000000000000000000)).ethRec(1000000000000000000)); + else // rounds over. need price for new round + return (75000000000000); + // init + } + + /** + * @dev returns time left. dont spam this, you'll ddos yourself from your node + * provider + * -functionhash- 0xc7e284b8 + * @return time left in seconds + */ + function getTimeLeft() + public + view + returns (uint256) + { + // setup local rID + uint256 _rID = rID_; + + // grab time + uint256 _now = now; + + if (_now < round_[_rID].end) + if (_now > round_[_rID].strt + rndGap_) + return ((round_[_rID].end).sub(_now)); + else + return ((round_[_rID].strt + rndGap_).sub(_now)); + else + return (0); + } + + /** + * @dev returns player earnings per vaults + * -functionhash- 0x63066434 + * @return winnings vault + * @return general vault + * @return affiliate vault + */ + function getPlayerVaults(uint256 _pID) + public + view + returns (uint256, uint256, uint256) + { + // setup local rID + uint256 _rID = rID_; + + // if round has ended. but round end has not been run (so contract has not distributed winnings) + if (now > round_[_rID].end && round_[_rID].ended == false && round_[_rID].plyr != 0) + { + // if player is winner + if (round_[_rID].plyr == _pID) + { + return + ( + (plyr_[_pID].win).add(((round_[_rID].pot).mul(48)) / 100), + (plyr_[_pID].gen).add(getPlayerVaultsHelper(_pID, _rID).sub(plyrRnds_[_pID][_rID].mask)), + plyr_[_pID].aff + ); + // if player is not the winner + } else { + return + ( + plyr_[_pID].win, + (plyr_[_pID].gen).add(getPlayerVaultsHelper(_pID, _rID).sub(plyrRnds_[_pID][_rID].mask)), + plyr_[_pID].aff + ); + } + + // if round is still going on, or round has ended and round end has been ran + } else { + return + ( + plyr_[_pID].win, + (plyr_[_pID].gen).add(calcUnMaskedEarnings(_pID, plyr_[_pID].lrnd)), + plyr_[_pID].aff + ); + } + } + + /** + * solidity hates stack limits. this lets us avoid that hate + */ + function getPlayerVaultsHelper(uint256 _pID, uint256 _rID) + private + view + returns (uint256) + { + return (((((round_[_rID].mask).add(((((round_[_rID].pot).mul(potSplit_[round_[_rID].team].gen)) / 100).mul(1000000000000000000)) / (round_[_rID].keys))).mul(plyrRnds_[_pID][_rID].keys)) / 1000000000000000000)); + } + + /** + * @dev returns all current round info needed for front end + * -functionhash- 0x747dff42 + * @return eth invested during ICO phase + * @return round id + * @return total keys for round + * @return time round ends + * @return time round started + * @return current pot + * @return current team ID & player ID in lead + * @return current player in leads address + * @return current player in leads name + * @return whales eth in for round + * @return bears eth in for round + * @return sneks eth in for round + * @return bulls eth in for round + * @return airdrop tracker # & airdrop pot + */ + function getCurrentRoundInfo() + public + view + returns (uint256, uint256, uint256, uint256, uint256, uint256, uint256, address, bytes32, uint256, uint256, uint256, uint256, uint256) + { + // setup local rID + uint256 _rID = rID_; + + return + ( + round_[_rID].ico, //0 + _rID, //1 + round_[_rID].keys, //2 + round_[_rID].end, //3 + round_[_rID].strt, //4 + round_[_rID].pot, //5 + (round_[_rID].team + (round_[_rID].plyr * 10)), //6 + plyr_[round_[_rID].plyr].addr, //7 + plyr_[round_[_rID].plyr].name, //8 + rndTmEth_[_rID][0], //9 + rndTmEth_[_rID][1], //10 + rndTmEth_[_rID][2], //11 + rndTmEth_[_rID][3], //12 + airDropTracker_ + (airDropPot_ * 1000) //13 + ); + } + + /** + * @dev returns player info based on address. if no address is given, it will + * use msg.sender + * -functionhash- 0xee0b5d8b + * @param _addr address of the player you want to lookup + * @return player ID + * @return player name + * @return keys owned (current round) + * @return winnings vault + * @return general vault + * @return affiliate vault + * @return player round eth + */ + function getPlayerInfoByAddress(address _addr) + public + view + returns (uint256, bytes32, uint256, uint256, uint256, uint256, uint256) + { + // setup local rID + uint256 _rID = rID_; + + if (_addr == address(0)) + { + _addr == msg.sender; + } + uint256 _pID = pIDxAddr_[_addr]; + + return + ( + _pID, //0 + plyr_[_pID].name, //1 + plyrRnds_[_pID][_rID].keys, //2 + plyr_[_pID].win, //3 + (plyr_[_pID].gen).add(calcUnMaskedEarnings(_pID, plyr_[_pID].lrnd)), //4 + plyr_[_pID].aff, //5 + plyrRnds_[_pID][_rID].eth //6 + ); + } + + //============================================================================== + // _ _ _ _ | _ _ . _ . + // (_(_)| (/_ |(_)(_||(_ . (this + tools + calcs + modules = our softwares engine) + //=====================_|======================================================= + /** + * @dev logic runs whenever a buy order is executed. determines how to handle + * incoming eth depending on if we are in an active round or not + */ + function buyCore(uint256 _pID, uint256 _affID, uint256 _team, F3Ddatasets.EventReturns memory _eventData_) + private + { + // setup local rID + uint256 _rID = rID_; + + // grab time + uint256 _now = now; + + // if round is active + if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) + { + // call core + core(_rID, _pID, msg.value, _affID, _team, _eventData_); + + // if round is not active + } else { + // check to see if end round needs to be ran + if (_now > round_[_rID].end && round_[_rID].ended == false) + { + // end the round (distributes pot) & start new round + round_[_rID].ended = true; + _eventData_ = endRound(_eventData_); + + // build event data + _eventData_.compressedData = _eventData_.compressedData + (_now * 1000000000000000000); + _eventData_.compressedIDs = _eventData_.compressedIDs + _pID; + + // fire buy and distribute event + emit F3Devents.onBuyAndDistribute + ( + msg.sender, + plyr_[_pID].name, + msg.value, + _eventData_.compressedData, + _eventData_.compressedIDs, + _eventData_.winnerAddr, + _eventData_.winnerName, + _eventData_.amountWon, + _eventData_.newPot, + _eventData_.P3DAmount, + _eventData_.genAmount + ); + } + + // put eth in players vault + plyr_[_pID].gen = plyr_[_pID].gen.add(msg.value); + } + } + + /** + * @dev logic runs whenever a reload order is executed. determines how to handle + * incoming eth depending on if we are in an active round or not + */ + function reLoadCore(uint256 _pID, uint256 _affID, uint256 _team, uint256 _eth, F3Ddatasets.EventReturns memory _eventData_) + private + { + // setup local rID + uint256 _rID = rID_; + + // grab time + uint256 _now = now; + + // if round is active + if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) + { + // get earnings from all vaults and return unused to gen vault + // because we use a custom safemath library. this will throw if player + // tried to spend more eth than they have. + plyr_[_pID].gen = withdrawEarnings(_pID).sub(_eth); + + // call core + core(_rID, _pID, _eth, _affID, _team, _eventData_); + + // if round is not active and end round needs to be ran + } else if (_now > round_[_rID].end && round_[_rID].ended == false) { + // end the round (distributes pot) & start new round + round_[_rID].ended = true; + _eventData_ = endRound(_eventData_); + + // build event data + _eventData_.compressedData = _eventData_.compressedData + (_now * 1000000000000000000); + _eventData_.compressedIDs = _eventData_.compressedIDs + _pID; + + // fire buy and distribute event + emit F3Devents.onReLoadAndDistribute + ( + msg.sender, + plyr_[_pID].name, + _eventData_.compressedData, + _eventData_.compressedIDs, + _eventData_.winnerAddr, + _eventData_.winnerName, + _eventData_.amountWon, + _eventData_.newPot, + _eventData_.P3DAmount, + _eventData_.genAmount + ); + } + } + + /** + * @dev this is the core logic for any buy/reload that happens while a round + * is live. + */ + function core(uint256 _rID, uint256 _pID, uint256 _eth, uint256 _affID, uint256 _team, F3Ddatasets.EventReturns memory _eventData_) + private + { + // if player is new to round + if (plyrRnds_[_pID][_rID].keys == 0) + _eventData_ = managePlayer(_pID, _eventData_); + + // early round eth limiter + if (round_[_rID].eth < 100000000000000000000 && plyrRnds_[_pID][_rID].eth.add(_eth) > 1000000000000000000) + { + uint256 _availableLimit = (1000000000000000000).sub(plyrRnds_[_pID][_rID].eth); + uint256 _refund = _eth.sub(_availableLimit); + plyr_[_pID].gen = plyr_[_pID].gen.add(_refund); + _eth = _availableLimit; + } + + // if eth left is greater than min eth allowed (sorry no pocket lint) + if (_eth > 1000000000) + { + + // mint the new keys + uint256 _keys = (round_[_rID].eth).keysRec(_eth); + + // if they bought at least 1 whole key + if (_keys >= 1000000000000000000) + { + updateTimer(_keys, _rID); + + // set new leaders + if (round_[_rID].plyr != _pID) + round_[_rID].plyr = _pID; + if (round_[_rID].team != _team) + round_[_rID].team = _team; + + // set the new leader bool to true + _eventData_.compressedData = _eventData_.compressedData + 100; + } + + // manage airdrops + if (_eth >= 100000000000000000) + { + airDropTracker_++; + if (airdrop() == true) + { + // gib muni + uint256 _prize; + if (_eth >= 10000000000000000000) + { + // calculate prize and give it to winner + _prize = ((airDropPot_).mul(75)) / 100; + plyr_[_pID].win = (plyr_[_pID].win).add(_prize); + + // adjust airDropPot + airDropPot_ = (airDropPot_).sub(_prize); + + // let event know a tier 3 prize was won + _eventData_.compressedData += 300000000000000000000000000000000; + } else if (_eth >= 1000000000000000000 && _eth < 10000000000000000000) { + // calculate prize and give it to winner + _prize = ((airDropPot_).mul(50)) / 100; + plyr_[_pID].win = (plyr_[_pID].win).add(_prize); + + // adjust airDropPot + airDropPot_ = (airDropPot_).sub(_prize); + + // let event know a tier 2 prize was won + _eventData_.compressedData += 200000000000000000000000000000000; + } else if (_eth >= 100000000000000000 && _eth < 1000000000000000000) { + // calculate prize and give it to winner + _prize = ((airDropPot_).mul(25)) / 100; + plyr_[_pID].win = (plyr_[_pID].win).add(_prize); + + // adjust airDropPot + airDropPot_ = (airDropPot_).sub(_prize); + + // let event know a tier 3 prize was won + _eventData_.compressedData += 300000000000000000000000000000000; + } + // set airdrop happened bool to true + _eventData_.compressedData += 10000000000000000000000000000000; + // let event know how much was won + _eventData_.compressedData += _prize * 1000000000000000000000000000000000; + + // reset air drop tracker + airDropTracker_ = 0; + } + } + + // store the air drop tracker number (number of buys since last airdrop) + _eventData_.compressedData = _eventData_.compressedData + (airDropTracker_ * 1000); + + // update player + plyrRnds_[_pID][_rID].keys = _keys.add(plyrRnds_[_pID][_rID].keys); + plyrRnds_[_pID][_rID].eth = _eth.add(plyrRnds_[_pID][_rID].eth); + + // update round + round_[_rID].keys = _keys.add(round_[_rID].keys); + round_[_rID].eth = _eth.add(round_[_rID].eth); + rndTmEth_[_rID][_team] = _eth.add(rndTmEth_[_rID][_team]); + + // distribute eth + _eventData_ = distributeExternal(_rID, _pID, _eth, _affID, _team, _eventData_); + _eventData_ = distributeInternal(_rID, _pID, _eth, _team, _keys, _eventData_); + + // call end tx function to fire end tx event. + endTx(_pID, _team, _eth, _keys, _eventData_); + } + } + //============================================================================== + // _ _ | _ | _ _|_ _ _ _ . + // (_(_||(_|_||(_| | (_)| _\ . + //============================================================================== + /** + * @dev calculates unmasked earnings (just calculates, does not update mask) + * @return earnings in wei format + */ + function calcUnMaskedEarnings(uint256 _pID, uint256 _rIDlast) + private + view + returns (uint256) + { + return ((((round_[_rIDlast].mask).mul(plyrRnds_[_pID][_rIDlast].keys)) / (1000000000000000000)).sub(plyrRnds_[_pID][_rIDlast].mask)); + } + + /** + * @dev returns the amount of keys you would get given an amount of eth. + * -functionhash- 0xce89c80c + * @param _rID round ID you want price for + * @param _eth amount of eth sent in + * @return keys received + */ + function calcKeysReceived(uint256 _rID, uint256 _eth) + public + view + returns (uint256) + { + // grab time + uint256 _now = now; + + // are we in a round? + if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) + return ((round_[_rID].eth).keysRec(_eth)); + else // rounds over. need keys for new round + return ((_eth).keys()); + } + + /** + * @dev returns current eth price for X keys. + * -functionhash- 0xcf808000 + * @param _keys number of keys desired (in 18 decimal format) + * @return amount of eth needed to send + */ + function iWantXKeys(uint256 _keys) + public + view + returns (uint256) + { + // setup local rID + uint256 _rID = rID_; + + // grab time + uint256 _now = now; + + // are we in a round? + if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) + return ((round_[_rID].keys.add(_keys)).ethRec(_keys)); + else // rounds over. need price for new round + return ((_keys).eth()); + } + //============================================================================== + // _|_ _ _ | _ . + // | (_)(_)|_\ . + //============================================================================== + /** + * @dev receives name/player info from names contract + */ + function receivePlayerInfo(uint256 _pID, address _addr, bytes32 _name, uint256 _laff) + external + { + require(msg.sender == address(playerBook), "your not playerNames contract... hmmm.."); + if (pIDxAddr_[_addr] != _pID) + pIDxAddr_[_addr] = _pID; + if (pIDxName_[_name] != _pID) + pIDxName_[_name] = _pID; + if (plyr_[_pID].addr != _addr) + plyr_[_pID].addr = _addr; + if (plyr_[_pID].name != _name) + plyr_[_pID].name = _name; + if (plyr_[_pID].laff != _laff) + plyr_[_pID].laff = _laff; + if (plyrNames_[_pID][_name] == false) + plyrNames_[_pID][_name] = true; + } + + /** + * @dev receives entire player name list + */ + function receivePlayerNameList(uint256 _pID, bytes32 _name) + external + { + require(msg.sender == address(playerBook), "your not playerNames contract... hmmm.."); + if (plyrNames_[_pID][_name] == false) + plyrNames_[_pID][_name] = true; + } + + /** + * @dev gets existing or registers new pID. use this when a player may be new + * @return pID + */ + function determinePID(F3Ddatasets.EventReturns memory _eventData_) + private + returns (F3Ddatasets.EventReturns) + { + uint256 _pID = pIDxAddr_[msg.sender]; + // if player is new to this version of fomo3d + if (_pID == 0) + { + // grab their player ID, name and last aff ID, from player names contract + _pID = playerBook.getPlayerID(msg.sender); + bytes32 _name = playerBook.getPlayerName(_pID); + uint256 _laff = playerBook.getPlayerLAff(_pID); + + // set up player account + pIDxAddr_[msg.sender] = _pID; + plyr_[_pID].addr = msg.sender; + + if (_name != "") + { + pIDxName_[_name] = _pID; + plyr_[_pID].name = _name; + plyrNames_[_pID][_name] = true; + } + + if (_laff != 0 && _laff != _pID) + plyr_[_pID].laff = _laff; + + // set the new player bool to true + _eventData_.compressedData = _eventData_.compressedData + 1; + } + return (_eventData_); + } + + /** + * @dev checks to make sure user picked a valid team. if not sets team + * to default (sneks) + */ + function verifyTeam(uint256 _team) + private + pure + returns (uint256) + { + if (_team < 0 || _team > 3) + return (2); + else + return (_team); + } + + /** + * @dev decides if round end needs to be run & new round started. and if + * player unmasked earnings from previously played rounds need to be moved. + */ + function managePlayer(uint256 _pID, F3Ddatasets.EventReturns memory _eventData_) + private + returns (F3Ddatasets.EventReturns) + { + // if player has played a previous round, move their unmasked earnings + // from that round to gen vault. + if (plyr_[_pID].lrnd != 0) + updateGenVault(_pID, plyr_[_pID].lrnd); + + // update player's last round played + plyr_[_pID].lrnd = rID_; + + // set the joined round bool to true + _eventData_.compressedData = _eventData_.compressedData + 10; + + return (_eventData_); + } + + /** + * @dev ends the round. manages paying out winner/splitting up pot + */ + function endRound(F3Ddatasets.EventReturns memory _eventData_) + private + returns (F3Ddatasets.EventReturns) + { + // setup local rID + uint256 _rID = rID_; + + // grab our winning player and team id's + uint256 _winPID = round_[_rID].plyr; + uint256 _winTID = round_[_rID].team; + + // grab our pot amount + uint256 _pot = round_[_rID].pot; + + // calculate our winner share, community rewards, gen share, + // p3d share, and amount reserved for next pot + uint256 _win = (_pot.mul(48)) / 100; + uint256 _com = (_pot / 50); + uint256 _gen = (_pot.mul(potSplit_[_winTID].gen)) / 100; + uint256 _p3d = (_pot.mul(potSplit_[_winTID].p3d)) / 100; + uint256 _res = (((_pot.sub(_win)).sub(_com)).sub(_gen)).sub(_p3d); + + // calculate ppt for round mask + uint256 _ppt = (_gen.mul(1000000000000000000)) / (round_[_rID].keys); + uint256 _dust = _gen.sub((_ppt.mul(round_[_rID].keys)) / 1000000000000000000); + if (_dust > 0) + { + _gen = _gen.sub(_dust); + _res = _res.add(_dust); + } + + // pay our winner + plyr_[_winPID].win = _win.add(plyr_[_winPID].win); + + // community rewards + if (!address(Jekyll_Island_Inc).send(_com)) + { + // This ensures Team Just cannot influence the outcome of FoMo3D with + // bank migrations by breaking outgoing transactions. + // Something we would never do. But that's not the point. + // We spent 2000$ in eth re-deploying just to patch this, we hold the + // highest belief that everything we create should be trustless. + // Team JUST, The name you shouldn't have to trust. + _p3d = _p3d.add(_com); + _com = 0; + } + + // distribute gen portion to key holders + round_[_rID].mask = _ppt.add(round_[_rID].mask); + + // send share for p3d to divies + if (_p3d > 0) + Divies.transfer(_p3d); + + // prepare event data + _eventData_.compressedData = _eventData_.compressedData + (round_[_rID].end * 1000000); + _eventData_.compressedIDs = _eventData_.compressedIDs + (_winPID * 100000000000000000000000000) + (_winTID * 100000000000000000); + _eventData_.winnerAddr = plyr_[_winPID].addr; + _eventData_.winnerName = plyr_[_winPID].name; + _eventData_.amountWon = _win; + _eventData_.genAmount = _gen; + _eventData_.P3DAmount = _p3d; + _eventData_.newPot = _res; + + // start next round + rID_++; + _rID++; + round_[_rID].strt = now; + round_[_rID].end = now.add(rndInit_).add(rndGap_); + round_[_rID].pot = _res; + + return (_eventData_); + } + + /** + * @dev moves any unmasked earnings to gen vault. updates earnings mask + */ + function updateGenVault(uint256 _pID, uint256 _rIDlast) + private + { + uint256 _earnings = calcUnMaskedEarnings(_pID, _rIDlast); + if (_earnings > 0) + { + // put in gen vault + plyr_[_pID].gen = _earnings.add(plyr_[_pID].gen); + // zero out their earnings by updating mask + plyrRnds_[_pID][_rIDlast].mask = _earnings.add(plyrRnds_[_pID][_rIDlast].mask); + } + } + + /** + * @dev updates round timer based on number of whole keys bought. + */ + function updateTimer(uint256 _keys, uint256 _rID) + private + { + // grab time + uint256 _now = now; + + // calculate time based on number of keys bought + uint256 _newTime; + if (_now > round_[_rID].end && round_[_rID].plyr == 0) + _newTime = (((_keys) / (1000000000000000000)).mul(rndInc_)).add(_now); + else + _newTime = (((_keys) / (1000000000000000000)).mul(rndInc_)).add(round_[_rID].end); + + // compare to max and set new end time + if (_newTime < (rndMax_).add(_now)) + round_[_rID].end = _newTime; + else + round_[_rID].end = rndMax_.add(_now); + } + + /** + * @dev generates a random number between 0-99 and checks to see if thats + * resulted in an airdrop win + * @return do we have a winner? + */ + function airdrop() + private + view + returns (bool) + { + uint256 seed = uint256(keccak256(abi.encodePacked( + + (block.timestamp).add + (block.difficulty).add + ((uint256(keccak256(abi.encodePacked(block.coinbase)))) / (now)).add + (block.gaslimit).add + ((uint256(keccak256(abi.encodePacked(msg.sender)))) / (now)).add + (block.number) + + ))); + if ((seed - ((seed / 1000) * 1000)) < airDropTracker_) + return (true); + else + return (false); + } + + /** + * @dev distributes eth based on fees to com, aff, and p3d + */ + function distributeExternal(uint256 _rID, uint256 _pID, uint256 _eth, uint256 _affID, uint256 _team, F3Ddatasets.EventReturns memory _eventData_) + private + returns (F3Ddatasets.EventReturns) + { + // pay 2% out to community rewards + uint256 _com = _eth / 50; + uint256 _p3d; + if (!address(Jekyll_Island_Inc).send(_com)) + { + // This ensures Team Just cannot influence the outcome of FoMo3D with + // bank migrations by breaking outgoing transactions. + // Something we would never do. But that's not the point. + // We spent 2000$ in eth re-deploying just to patch this, we hold the + // highest belief that everything we create should be trustless. + // Team JUST, The name you shouldn't have to trust. + _p3d = _com; + _com = 0; + } + + // pay 1% out to FoMo3D short + uint256 _long = _eth / 100; + otherF3D_.transfer(_long); + + // distribute share to affiliate + uint256 _aff = _eth / 10; + + // decide what to do with affiliate share of fees + // affiliate must not be self, and must have a name registered + if (_affID != _pID && plyr_[_affID].name != '') { + plyr_[_affID].aff = _aff.add(plyr_[_affID].aff); + emit F3Devents.onAffiliatePayout(_affID, plyr_[_affID].addr, plyr_[_affID].name, _rID, _pID, _aff, now); + } else { + _p3d = _aff; + } + + // pay out p3d + _p3d = _p3d.add((_eth.mul(fees_[_team].p3d)) / (100)); + if (_p3d > 0) + { + // deposit to divies contract + Divies.transfer(_p3d); + + // set up event data + _eventData_.P3DAmount = _p3d.add(_eventData_.P3DAmount); + } + + return (_eventData_); + } + + function potSwap() + external + payable + { + // setup local rID + uint256 _rID = rID_ + 1; + + round_[_rID].pot = round_[_rID].pot.add(msg.value); + emit F3Devents.onPotSwapDeposit(_rID, msg.value); + } + + /** + * @dev distributes eth based on fees to gen and pot + */ + function distributeInternal(uint256 _rID, uint256 _pID, uint256 _eth, uint256 _team, uint256 _keys, F3Ddatasets.EventReturns memory _eventData_) + private + returns (F3Ddatasets.EventReturns) + { + // calculate gen share + uint256 _gen = (_eth.mul(fees_[_team].gen)) / 100; + + // toss 1% into airdrop pot + uint256 _air = (_eth / 100); + airDropPot_ = airDropPot_.add(_air); + + // update eth balance (eth = eth - (com share + pot swap share + aff share + p3d share + airdrop pot share)) + _eth = _eth.sub(((_eth.mul(14)) / 100).add((_eth.mul(fees_[_team].p3d)) / 100)); + + // calculate pot + uint256 _pot = _eth.sub(_gen); + + // distribute gen share (thats what updateMasks() does) and adjust + // balances for dust. + uint256 _dust = updateMasks(_rID, _pID, _gen, _keys); + if (_dust > 0) + _gen = _gen.sub(_dust); + + // add eth to pot + round_[_rID].pot = _pot.add(_dust).add(round_[_rID].pot); + + // set up event data + _eventData_.genAmount = _gen.add(_eventData_.genAmount); + _eventData_.potAmount = _pot; + + return (_eventData_); + } + + /** + * @dev updates masks for round and player when keys are bought + * @return dust left over + */ + function updateMasks(uint256 _rID, uint256 _pID, uint256 _gen, uint256 _keys) + private + returns (uint256) + { + /* MASKING NOTES + earnings masks are a tricky thing for people to wrap their minds around. + the basic thing to understand here. is were going to have a global + tracker based on profit per share for each round, that increases in + relevant proportion to the increase in share supply. + + the player will have an additional mask that basically says "based + on the rounds mask, my shares, and how much i've already withdrawn, + how much is still owed to me?" + */ + + // calc profit per key & round mask based on this buy: (dust goes to pot) + uint256 _ppt = (_gen.mul(1000000000000000000)) / (round_[_rID].keys); + round_[_rID].mask = _ppt.add(round_[_rID].mask); + + // calculate player earning from their own buy (only based on the keys + // they just bought). & update player earnings mask + uint256 _pearn = (_ppt.mul(_keys)) / (1000000000000000000); + plyrRnds_[_pID][_rID].mask = (((round_[_rID].mask.mul(_keys)) / (1000000000000000000)).sub(_pearn)).add(plyrRnds_[_pID][_rID].mask); + + // calculate & return dust + return (_gen.sub((_ppt.mul(round_[_rID].keys)) / (1000000000000000000))); + } + + /** + * @dev adds up unmasked earnings, & vault earnings, sets them all to 0 + * @return earnings in wei format + */ + function withdrawEarnings(uint256 _pID) + private + returns (uint256) + { + // update gen vault + updateGenVault(_pID, plyr_[_pID].lrnd); + + // from vaults + uint256 _earnings = (plyr_[_pID].win).add(plyr_[_pID].gen).add(plyr_[_pID].aff); + if (_earnings > 0) + { + plyr_[_pID].win = 0; + plyr_[_pID].gen = 0; + plyr_[_pID].aff = 0; + } + + return (_earnings); + } + + /** + * @dev prepares compression data and fires event for buy or reload tx's + */ + function endTx(uint256 _pID, uint256 _team, uint256 _eth, uint256 _keys, F3Ddatasets.EventReturns memory _eventData_) + private + { + _eventData_.compressedData = _eventData_.compressedData + (now * 1000000000000000000) + (_team * 100000000000000000000000000000); + _eventData_.compressedIDs = _eventData_.compressedIDs + _pID + (rID_ * 10000000000000000000000000000000000000000000000000000); + + emit F3Devents.onEndTx + ( + _eventData_.compressedData, + _eventData_.compressedIDs, + plyr_[_pID].name, + msg.sender, + _eth, + _keys, + _eventData_.winnerAddr, + _eventData_.winnerName, + _eventData_.amountWon, + _eventData_.newPot, + _eventData_.P3DAmount, + _eventData_.genAmount, + _eventData_.potAmount, + airDropPot_ + ); + } + //============================================================================== + // (~ _ _ _._|_ . + // _)(/_(_|_|| | | \/ . + //====================/========================================================= + /** upon contract deploy, it will be deactivated. this is a one time + * use function that will activate the contract. we do this so devs + * have time to set things up on the web end **/ + bool public activated_ = false; + + function activate() + public + onlyDevs + { + + // can only be ran once + require(activated_ == false, "fomo3d already activated"); + + // activate the contract + activated_ = true; + + otherF3D_ = msg.sender; + Divies = msg.sender; + Jekyll_Island_Inc = msg.sender; + + // lets start first round + rID_ = 1; + round_[1].strt = now + rndExtra_ - rndGap_; + round_[1].end = now + rndInit_ + rndExtra_; + } + + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractScenario007.sol b/src/test/resources/soliditycode_v0.4.25/contractScenario007.sol new file mode 100644 index 00000000000..44aae1a5e32 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractScenario007.sol @@ -0,0 +1,1433 @@ +//pragma solidity 0.4.24; + +/** + * @title ERC165 + * @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md + */ +interface ERC165 { + + /** + * @notice Query if a contract implements an interface + * @param _interfaceId The interface identifier, as specified in ERC-165 + * @dev Interface identification is specified in ERC-165. This function + * uses less than 30,000 gas. + */ + function supportsInterface(bytes4 _interfaceId) external view returns (bool); + +} + +contract ERC721Basic is ERC165 { + + event Transfer( + address indexed _from, + address indexed _to, + uint256 indexed _tokenId + ); + event Approval( + address indexed _owner, + address indexed _approved, + uint256 indexed _tokenId + ); + event ApprovalForAll( + address indexed _owner, + address indexed _operator, + bool _approved + ); + + function balanceOf(address _owner) public view returns (uint256 _balance); + function ownerOf(uint256 _tokenId) public view returns (address _owner); + function exists(uint256 _tokenId) public view returns (bool _exists); + + function approve(address _to, uint256 _tokenId) public; + function getApproved(uint256 _tokenId) + public view returns (address _operator); + + function setApprovalForAll(address _operator, bool _approved) public; + function isApprovedForAll(address _owner, address _operator) + public view returns (bool); + + function transferFrom(address _from, address _to, uint256 _tokenId) public; + function safeTransferFrom(address _from, address _to, uint256 _tokenId) + public; + + function safeTransferFrom( + address _from, + address _to, + uint256 _tokenId, + bytes memory _data + ) + public; +} + + +/** + * @title SupportsInterfaceWithLookup + * @author Matt Condon (@shrugs) + * @dev Implements ERC165 using a lookup table. + */ +contract SupportsInterfaceWithLookup is ERC165 { + bytes4 public constant InterfaceId_ERC165 = 0x01ffc9a7; + /** + * 0x01ffc9a7 === + * bytes4(keccak256('supportsInterface(bytes4)')) + */ + + /** + * @dev a mapping of interface id to whether or not it's supported + */ + mapping(bytes4 => bool) internal supportedInterfaces; + + /** + * @dev A contract implementing SupportsInterfaceWithLookup + * implement ERC165 itself + */ + constructor() public { + _registerInterface(InterfaceId_ERC165); + } + + /** + * @dev implement supportsInterface(bytes4) using a lookup table + */ + function supportsInterface(bytes4 _interfaceId) external view returns (bool) { + return supportedInterfaces[_interfaceId]; + } + + /** + * @dev private method for registering an interface + */ + function _registerInterface(bytes4 _interfaceId) internal { + require(_interfaceId != 0xffffffff); + supportedInterfaces[_interfaceId] = true; + } +} + +contract Governable { + + event Pause(); + event Unpause(); + + address public governor; + bool public paused = false; + + constructor() public { + governor = msg.sender; + } + + function setGovernor(address _gov) public onlyGovernor { + governor = _gov; + } + + modifier onlyGovernor { + require(msg.sender == governor); + _; + } + + /** + * @dev Modifier to make a function callable only when the contract is not paused. + */ + modifier whenNotPaused() { + require(!paused); + _; + } + + /** + * @dev Modifier to make a function callable only when the contract is paused. + */ + modifier whenPaused() { + require(paused); + _; + } + + /** + * @dev called by the owner to pause, triggers stopped state + */ + function pause() onlyGovernor whenNotPaused public { + paused = true; + emit Pause(); + } + + /** + * @dev called by the owner to unpause, returns to normal state + */ + function unpause() onlyGovernor whenPaused public { + paused = false; + emit Unpause(); + } + +} + +contract CardBase is Governable { + + struct Card { + uint16 proto; + uint16 purity; + } + + function getCard(uint id) public view returns (uint16 proto, uint16 purity) { + Card memory card = cards[id]; + return (card.proto, card.purity); + } + + function getShine(uint16 purity) public pure returns (uint8) { + return uint8(purity / 1000); + } + + Card[] public cards; + +} + +contract CardProto is CardBase { + + event NewProtoCard( + uint16 id, uint8 season, uint8 god, + Rarity rarity, uint8 mana, uint8 attack, + uint8 health, uint8 cardType, uint8 tribe, bool packable + ); + + struct Limit { + uint64 limit; + bool exists; + } + + // limits for mythic cards + mapping(uint16 => Limit) public limits; + + // can only set limits once + function setLimit(uint16 id, uint64 limit) public onlyGovernor { + Limit memory l = limits[id]; + require(!l.exists); + limits[id] = Limit({ + limit: limit, + exists: true + }); + } + + function getLimit(uint16 id) public view returns (uint64 limit, bool set) { + Limit memory l = limits[id]; + return (l.limit, l.exists); + } + + // could make these arrays to save gas + // not really necessary - will be update a very limited no of times + mapping(uint8 => bool) public seasonTradable; + mapping(uint8 => bool) public seasonTradabilityLocked; + uint8 public currentSeason; + + function makeTradable(uint8 season) public onlyGovernor { + seasonTradable[season] = true; + } + + function makeUntradable(uint8 season) public onlyGovernor { + require(!seasonTradabilityLocked[season]); + seasonTradable[season] = false; + } + + function makePermanantlyTradable(uint8 season) public onlyGovernor { + require(seasonTradable[season]); + seasonTradabilityLocked[season] = true; + } + + function isTradable(uint16 proto) public view returns (bool) { + return seasonTradable[protos[proto].season]; + } + + function nextSeason() public onlyGovernor { + //Seasons shouldn't go to 0 if there is more than the uint8 should hold, the governor should know this ¯\_(ツ)_/¯ -M + require(currentSeason <= 255); + + currentSeason++; + mythic.length = 0; + legendary.length = 0; + epic.length = 0; + rare.length = 0; + common.length = 0; + } + + enum Rarity { + Common, + Rare, + Epic, + Legendary, + Mythic + } + + uint8 constant SPELL = 1; + uint8 constant MINION = 2; + uint8 constant WEAPON = 3; + uint8 constant HERO = 4; + + struct ProtoCard { + bool exists; + uint8 god; + uint8 season; + uint8 cardType; + Rarity rarity; + uint8 mana; + uint8 attack; + uint8 health; + uint8 tribe; + } + + // there is a particular design decision driving this: + // need to be able to iterate over mythics only for card generation + // don't store 5 different arrays: have to use 2 ids + // better to bear this cost (2 bytes per proto card) + // rather than 1 byte per instance + + uint16 public protoCount; + + mapping(uint16 => ProtoCard) protos; + + uint16[] public mythic; + uint16[] public legendary; + uint16[] public epic; + uint16[] public rare; + uint16[] public common; + + function addProtos( + uint16[] memory externalIDs, uint8[] memory gods, Rarity[] memory rarities, uint8[] memory manas, uint8[] memory attacks, + uint8[] memory healths, uint8[] memory cardTypes, uint8[] memory tribes, bool[] memory packable + ) public onlyGovernor returns(uint16) { + + for (uint i = 0; i < externalIDs.length; i++) { + + ProtoCard memory card = ProtoCard({ + exists: true, + god: gods[i], + season: currentSeason, + cardType: cardTypes[i], + rarity: rarities[i], + mana: manas[i], + attack: attacks[i], + health: healths[i], + tribe: tribes[i] + }); + + _addProto(externalIDs[i], card, packable[i]); + } + + } + + function addProto( + uint16 externalID, uint8 god, Rarity rarity, uint8 mana, uint8 attack, uint8 health, uint8 cardType, uint8 tribe, bool packable + ) public onlyGovernor returns(uint16) { + ProtoCard memory card = ProtoCard({ + exists: true, + god: god, + season: currentSeason, + cardType: cardType, + rarity: rarity, + mana: mana, + attack: attack, + health: health, + tribe: tribe + }); + + _addProto(externalID, card, packable); + } + + function addWeapon( + uint16 externalID, uint8 god, Rarity rarity, uint8 mana, uint8 attack, uint8 durability, bool packable + ) public onlyGovernor returns(uint16) { + + ProtoCard memory card = ProtoCard({ + exists: true, + god: god, + season: currentSeason, + cardType: WEAPON, + rarity: rarity, + mana: mana, + attack: attack, + health: durability, + tribe: 0 + }); + + _addProto(externalID, card, packable); + } + + function addSpell(uint16 externalID, uint8 god, Rarity rarity, uint8 mana, bool packable) public onlyGovernor returns(uint16) { + + ProtoCard memory card = ProtoCard({ + exists: true, + god: god, + season: currentSeason, + cardType: SPELL, + rarity: rarity, + mana: mana, + attack: 0, + health: 0, + tribe: 0 + }); + + _addProto(externalID, card, packable); + } + + function addMinion( + uint16 externalID, uint8 god, Rarity rarity, uint8 mana, uint8 attack, uint8 health, uint8 tribe, bool packable + ) public onlyGovernor returns(uint16) { + + ProtoCard memory card = ProtoCard({ + exists: true, + god: god, + season: currentSeason, + cardType: MINION, + rarity: rarity, + mana: mana, + attack: attack, + health: health, + tribe: tribe + }); + + _addProto(externalID, card, packable); + } + + function _addProto(uint16 externalID, ProtoCard memory card, bool packable) internal { + + require(!protos[externalID].exists); + + card.exists = true; + + protos[externalID] = card; + + protoCount++; + + emit NewProtoCard( + externalID, currentSeason, card.god, + card.rarity, card.mana, card.attack, + card.health, card.cardType, card.tribe, packable + ); + + if (packable) { + Rarity rarity = card.rarity; + if (rarity == Rarity.Common) { + common.push(externalID); + } else if (rarity == Rarity.Rare) { + rare.push(externalID); + } else if (rarity == Rarity.Epic) { + epic.push(externalID); + } else if (rarity == Rarity.Legendary) { + legendary.push(externalID); + } else if (rarity == Rarity.Mythic) { + mythic.push(externalID); + } else { + require(false); + } + } + } + + function getProto(uint16 id) public view returns( + bool exists, uint8 god, uint8 season, uint8 cardType, Rarity rarity, uint8 mana, uint8 attack, uint8 health, uint8 tribe + ) { + ProtoCard memory proto = protos[id]; + return ( + proto.exists, + proto.god, + proto.season, + proto.cardType, + proto.rarity, + proto.mana, + proto.attack, + proto.health, + proto.tribe + ); + } + + function getRandomCard(Rarity rarity, uint16 random) public view returns (uint16) { + // modulo bias is fine - creates rarity tiers etc + // will obviously revert is there are no cards of that type: this is expected - should never happen + if (rarity == Rarity.Common) { + return common[random % common.length]; + } else if (rarity == Rarity.Rare) { + return rare[random % rare.length]; + } else if (rarity == Rarity.Epic) { + return epic[random % epic.length]; + } else if (rarity == Rarity.Legendary) { + return legendary[random % legendary.length]; + } else if (rarity == Rarity.Mythic) { + // make sure a mythic is available + uint16 id; + uint64 limit; + bool set; + for (uint i = 0; i < mythic.length; i++) { + id = mythic[(random + i) % mythic.length]; + (limit, set) = getLimit(id); + if (set && limit > 0){ + return id; + } + } + // if not, they get a legendary :( + return legendary[random % legendary.length]; + } + require(false); + return 0; + } + + // can never adjust tradable cards + // each season gets a 'balancing beta' + // totally immutable: season, rarity + function replaceProto( + uint16 index, uint8 god, uint8 cardType, uint8 mana, uint8 attack, uint8 health, uint8 tribe + ) public onlyGovernor { + ProtoCard memory pc = protos[index]; + require(!seasonTradable[pc.season]); + protos[index] = ProtoCard({ + exists: true, + god: god, + season: pc.season, + cardType: cardType, + rarity: pc.rarity, + mana: mana, + attack: attack, + health: health, + tribe: tribe + }); + } + +} + +contract ERC721Receiver { + /** + * @dev Magic value to be returned upon successful reception of an NFT + * Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`, + * which can be also obtained as `ERC721Receiver(0).onERC721Received.selector` + */ + bytes4 internal constant ERC721_RECEIVED = 0x150b7a02; + + /** + * @notice Handle the receipt of an NFT + * @dev The ERC721 smart contract calls this function on the recipient + * after a `safetransfer`. This function MAY throw to revert and reject the + * transfer. Return of other than the magic value MUST result in the + * transaction being reverted. + * Note: the contract address is always the message sender. + * @param _operator The address which called `safeTransferFrom` function + * @param _from The address which previously owned the token + * @param _tokenId The NFT identifier which is being transfered + * @param _data Additional data with no specified format + * @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` + */ + function onERC721Received( + address _operator, + address _from, + uint256 _tokenId, + bytes memory _data + ) + public + returns(bytes4); +} + +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; + } + +} + +library SafeMath { + + /** + * @dev Multiplies two numbers, throws on overflow. + */ + function mul(uint256 a, uint256 b) internal pure returns (uint256 c) { + // Gas optimization: this is cheaper than asserting 'a' not being zero, but the + // benefit is lost if 'b' is also tested. + // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 + if (a == 0) { + return 0; + } + + c = a * b; + assert(c / a == b); + return c; + } + + /** + * @dev Integer division of two numbers, truncating the quotient. + */ + function div(uint256 a, uint256 b) internal pure returns (uint256) { + // assert(b > 0); // Solidity automatically throws when dividing by 0 + // uint256 c = a / b; + // assert(a == b * c + a % b); // There is no case in which this doesn't hold + return a / b; + } + + /** + * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). + */ + function sub(uint256 a, uint256 b) internal pure returns (uint256) { + assert(b <= a); + return a - b; + } + + /** + * @dev Adds two numbers, throws on overflow. + */ + function add(uint256 a, uint256 b) internal pure returns (uint256 c) { + c = a + b; + assert(c >= a); + return c; + } +} + +contract ERC721BasicToken is CardProto, SupportsInterfaceWithLookup, ERC721Basic { + + bytes4 private constant InterfaceId_ERC721 = 0x80ac58cd; + /* + * 0x80ac58cd === + * bytes4(keccak256('balanceOf(address)')) ^ + * bytes4(keccak256('ownerOf(uint256)')) ^ + * bytes4(keccak256('approve(address,uint256)')) ^ + * bytes4(keccak256('getApproved(uint256)')) ^ + * bytes4(keccak256('setApprovalForAll(address,bool)')) ^ + * bytes4(keccak256('isApprovedForAll(address,address)')) ^ + * bytes4(keccak256('transferFrom(address,address,uint256)')) ^ + * bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^ + * bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) + */ + + bytes4 private constant InterfaceId_ERC721Exists = 0x4f558e79; + /* + * 0x4f558e79 === + * bytes4(keccak256('exists(uint256)')) + */ + + using SafeMath for uint256; + using AddressUtils for address; + + // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` + // which can be also obtained as `ERC721Receiver(0).onERC721Received.selector` + bytes4 private constant ERC721_RECEIVED = 0x150b7a02; + + // Mapping from token ID to owner + mapping (uint256 => address) internal tokenOwner; + + // Mapping from token ID to approved address + mapping (uint256 => address) internal tokenApprovals; + + // Mapping from owner to number of owned token + // mapping (address => uint256) internal ownedTokensCount; + + // Mapping from owner to operator approvals + mapping (address => mapping (address => bool)) internal operatorApprovals; + + /** + * @dev Guarantees msg.sender is owner of the given token + * @param _tokenId uint256 ID of the token to validate its ownership belongs to msg.sender + */ + modifier onlyOwnerOf(uint256 _tokenId) { + require(ownerOf(_tokenId) == msg.sender); + _; + } + + /** + * @dev Checks msg.sender can transfer a token, by being owner, approved, or operator + * @param _tokenId uint256 ID of the token to validate + */ + modifier canTransfer(uint256 _tokenId) { + require(isApprovedOrOwner(msg.sender, _tokenId)); + _; + } + + constructor() + public + { + // register the supported interfaces to conform to ERC721 via ERC165 + _registerInterface(InterfaceId_ERC721); + _registerInterface(InterfaceId_ERC721Exists); + } + + /** + * @dev Gets the balance of the specified address + * @param _owner address to query the balance of + * @return uint256 representing the amount owned by the passed address + */ + function balanceOf(address _owner) public view returns (uint256); + + /** + * @dev Gets the owner of the specified token ID + * @param _tokenId uint256 ID of the token to query the owner of + * @return owner address currently marked as the owner of the given token ID + */ + function ownerOf(uint256 _tokenId) public view returns (address) { + address owner = tokenOwner[_tokenId]; + require(owner != address(0)); + return owner; + } + + /** + * @dev Returns whether the specified token exists + * @param _tokenId uint256 ID of the token to query the existence of + * @return whether the token exists + */ + function exists(uint256 _tokenId) public view returns (bool) { + address owner = tokenOwner[_tokenId]; + return owner != address(0); + } + + /** + * @dev Approves another address to transfer the given token ID + * The zero address indicates there is no approved address. + * There can only be one approved address per token at a given time. + * Can only be called by the token owner or an approved operator. + * @param _to address to be approved for the given token ID + * @param _tokenId uint256 ID of the token to be approved + */ + function approve(address _to, uint256 _tokenId) public { + address owner = ownerOf(_tokenId); + require(_to != owner); + require(msg.sender == owner || isApprovedForAll(owner, msg.sender)); + + tokenApprovals[_tokenId] = _to; + emit Approval(owner, _to, _tokenId); + } + + /** + * @dev Gets the approved address for a token ID, or zero if no address set + * @param _tokenId uint256 ID of the token to query the approval of + * @return address currently approved for the given token ID + */ + function getApproved(uint256 _tokenId) public view returns (address) { + return tokenApprovals[_tokenId]; + } + + /** + * @dev Sets or unsets the approval of a given operator + * An operator is allowed to transfer all tokens of the sender on their behalf + * @param _to operator address to set the approval + * @param _approved representing the status of the approval to be set + */ + function setApprovalForAll(address _to, bool _approved) public { + require(_to != msg.sender); + operatorApprovals[msg.sender][_to] = _approved; + emit ApprovalForAll(msg.sender, _to, _approved); + } + + /** + * @dev Tells whether an operator is approved by a given owner + * @param _owner owner address which you want to query the approval of + * @param _operator operator address which you want to query the approval of + * @return bool whether the given operator is approved by the given owner + */ + function isApprovedForAll( + address _owner, + address _operator + ) + public + view + returns (bool) + { + return operatorApprovals[_owner][_operator]; + } + + /** + * @dev Transfers the ownership of a given token ID to another address + * Usage of this method is discouraged, use `safeTransferFrom` whenever possible + * Requires the msg sender to be the owner, approved, or operator + * @param _from current owner of the token + * @param _to address to receive the ownership of the given token ID + * @param _tokenId uint256 ID of the token to be transferred + */ + function transferFrom( + address _from, + address _to, + uint256 _tokenId + ) + public + canTransfer(_tokenId) + { + require(_from != address(0)); + require(_to != address(0)); + + clearApproval(_from, _tokenId); + removeTokenFrom(_from, _tokenId); + addTokenTo(_to, _tokenId); + + emit Transfer(_from, _to, _tokenId); + } + + /** + * @dev Safely transfers the ownership of a given token ID to another address + * If the target address is a contract, it must implement `onERC721Received`, + * which is called upon a safe transfer, and return the magic value + * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, + * the transfer is reverted. + * + * Requires the msg sender to be the owner, approved, or operator + * @param _from current owner of the token + * @param _to address to receive the ownership of the given token ID + * @param _tokenId uint256 ID of the token to be transferred + */ + function safeTransferFrom( + address _from, + address _to, + uint256 _tokenId + ) + public + canTransfer(_tokenId) + { + // solium-disable-next-line arg-overflow + safeTransferFrom(_from, _to, _tokenId, ""); + } + + /** + * @dev Safely transfers the ownership of a given token ID to another address + * If the target address is a contract, it must implement `onERC721Received`, + * which is called upon a safe transfer, and return the magic value + * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, + * the transfer is reverted. + * Requires the msg sender to be the owner, approved, or operator + * @param _from current owner of the token + * @param _to address to receive the ownership of the given token ID + * @param _tokenId uint256 ID of the token to be transferred + * @param _data bytes data to send along with a safe transfer check + */ + function safeTransferFrom( + address _from, + address _to, + uint256 _tokenId, + bytes memory _data + ) + public + canTransfer(_tokenId) + { + transferFrom(_from, _to, _tokenId); + // solium-disable-next-line arg-overflow + require(checkAndCallSafeTransfer(_from, _to, _tokenId, _data)); + } + + /** + * @dev Returns whether the given spender can transfer a given token ID + * @param _spender address of the spender to query + * @param _tokenId uint256 ID of the token to be transferred + * @return bool whether the msg.sender is approved for the given token ID, + * is an operator of the owner, or is the owner of the token + */ + function isApprovedOrOwner( + address _spender, + uint256 _tokenId + ) + internal + view + returns (bool) + { + address owner = ownerOf(_tokenId); + // Disable solium check because of + // https://github.com/duaraghav8/Solium/issues/175 + // solium-disable-next-line operator-whitespace + return ( + _spender == owner || + getApproved(_tokenId) == _spender || + isApprovedForAll(owner, _spender) + ); + } + + /** + * @dev Internal function to clear current approval of a given token ID + * Reverts if the given address is not indeed the owner of the token + * @param _owner owner of the token + * @param _tokenId uint256 ID of the token to be transferred + */ + function clearApproval(address _owner, uint256 _tokenId) internal { + require(ownerOf(_tokenId) == _owner); + if (tokenApprovals[_tokenId] != address(0)) { + tokenApprovals[_tokenId] = address(0); + } + } + + /** + * @dev Internal function to mint a new token + * Reverts if the given token ID already exists + * @param _to The address that will own the minted token + * @param _tokenId uint256 ID of the token to be minted by the msg.sender + */ + function _mint(address _to, uint256 _tokenId) internal { + require(_to != address(0)); + addNewTokenTo(_to, _tokenId); + emit Transfer(address(0), _to, _tokenId); + } + + + /** + * @dev Internal function to burn a specific token + * Reverts if the token does not exist + * @param _tokenId uint256 ID of the token being burned by the msg.sender + */ + function _burn(address _owner, uint256 _tokenId) internal { + clearApproval(_owner, _tokenId); + removeTokenFrom(_owner, _tokenId); + emit Transfer(_owner, address(0), _tokenId); + } + + function addNewTokenTo(address _to, uint256 _tokenId) internal { + require(tokenOwner[_tokenId] == address(0)); + tokenOwner[_tokenId] = _to; + } + + /** + * @dev Internal function to add a token ID to the list of a given address + * @param _to address representing the new owner of the given token ID + * @param _tokenId uint256 ID of the token to be added to the tokens list of the given address + */ + function addTokenTo(address _to, uint256 _tokenId) internal { + require(tokenOwner[_tokenId] == address(0)); + tokenOwner[_tokenId] = _to; + // ownedTokensCount[_to] = ownedTokensCount[_to].add(1); + } + + /** + * @dev Internal function to remove a token ID from the list of a given address + * @param _from address representing the previous owner of the given token ID + * @param _tokenId uint256 ID of the token to be removed from the tokens list of the given address + */ + function removeTokenFrom(address _from, uint256 _tokenId) internal { + require(ownerOf(_tokenId) == _from); + // ownedTokensCount[_from] = ownedTokensCount[_from].sub(1); + tokenOwner[_tokenId] = address(0); + } + + /** + * @dev Internal function to invoke `onERC721Received` on a target address + * The call is not executed if the target address is not a contract + * @param _from address representing the previous owner of the given token ID + * @param _to target address that will receive the tokens + * @param _tokenId uint256 ID of the token to be transferred + * @param _data bytes optional data to send along with the call + * @return whether the call correctly returned the expected magic value + */ + function checkAndCallSafeTransfer( + address _from, + address _to, + uint256 _tokenId, + bytes memory _data + ) + internal + returns (bool) + { + if (!_to.isContract()) { + return true; + } + bytes4 retval = ERC721Receiver(_to).onERC721Received( + msg.sender, _from, _tokenId, _data); + return (retval == ERC721_RECEIVED); + } + +} + + + +contract ERC721Enumerable is ERC721Basic { + function totalSupply() public view returns (uint256); + function tokenOfOwnerByIndex( + address _owner, + uint256 _index + ) + public + view + returns (uint256 _tokenId); + + function tokenByIndex(uint256 _index) public view returns (uint256); +} + +contract ERC721Metadata is ERC721Basic { + function name() external view returns (string memory _name); + function symbol() external view returns (string memory _symbol); + function tokenURI(uint256 _tokenId) public view returns (string memory); +} + +contract ERC721 is ERC721Basic, ERC721Enumerable, ERC721Metadata { + +} + + + + +library Strings { + + // via https://github.com/oraclize/ethereum-api/blob/master/oraclizeAPI_0.5.sol + function strConcat(string memory _a, string memory _b, string memory _c, string memory _d, string memory _e) internal pure returns (string memory ) { + bytes memory _ba = bytes(_a); + bytes memory _bb = bytes(_b); + bytes memory _bc = bytes(_c); + bytes memory _bd = bytes(_d); + bytes memory _be = bytes(_e); + string memory abcde = new string(_ba.length + _bb.length + _bc.length + _bd.length + _be.length); + bytes memory babcde = bytes(abcde); + uint k = 0; + for (uint i = 0; i < _ba.length; i++) babcde[k++] = _ba[i]; + for ( i = 0; i < _bb.length; i++) babcde[k++] = _bb[i]; + for ( i = 0; i < _bc.length; i++) babcde[k++] = _bc[i]; + for ( i = 0; i < _bd.length; i++) babcde[k++] = _bd[i]; + for ( i = 0; i < _be.length; i++) babcde[k++] = _be[i]; + return string(babcde); + } + + function strConcat(string memory _a, string memory _b, string memory _c, string memory _d) internal pure returns (string memory ) { + return strConcat(_a, _b, _c, _d, ""); + } + + function strConcat(string memory _a, string memory _b, string memory _c) internal pure returns (string memory ) { + return strConcat(_a, _b, _c, "", ""); + } + + function strConcat(string memory _a, string memory _b) internal pure returns (string memory ) { + return strConcat(_a, _b, "", "", ""); + } + + function uint2str(uint i) internal pure returns (string memory ) { + if (i == 0) return "0"; + uint j = i; + uint len; + while (j != 0){ + len++; + j /= 10; + } + bytes memory bstr = new bytes(len); + uint k = len - 1; + while (i != 0){ + bstr[k--] = byte(uint8(48 + i % 10)); + i /= 10; + } + return string(bstr); + } +} + +contract ERC721Token is SupportsInterfaceWithLookup, ERC721BasicToken, ERC721 { + + using Strings for string; + + bytes4 private constant InterfaceId_ERC721Enumerable = 0x780e9d63; + /** + * 0x780e9d63 === + * bytes4(keccak256('totalSupply()')) ^ + * bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) ^ + * bytes4(keccak256('tokenByIndex(uint256)')) + */ + + bytes4 private constant InterfaceId_ERC721Metadata = 0x5b5e139f; + /** + * 0x5b5e139f === + * bytes4(keccak256('name()')) ^ + * bytes4(keccak256('symbol()')) ^ + * bytes4(keccak256('tokenURI(uint256)')) + */ + + /*** Constants ***/ + // Configure these for your own deployment + string public constant NAME = "Gods Unchained"; + string public constant SYMBOL = "GODS"; + string public tokenMetadataBaseURI = "https://api.godsunchained.com/card/"; + + // Mapping from owner to list of owned token IDs + // EDITED: limit to 2^40 (around 1T) + mapping(address => uint40[]) internal ownedTokens; + + uint32[] ownedTokensIndex; + + /** + * @dev Constructor function + */ + constructor() public { + + // register the supported interfaces to conform to ERC721 via ERC165 + _registerInterface(InterfaceId_ERC721Enumerable); + _registerInterface(InterfaceId_ERC721Metadata); + } + + /** + * @dev Gets the token name + * @return string representing the token name + */ + function name() external view returns (string memory) { + return NAME; + } + + /** + * @dev Gets the token symbol + * @return string representing the token symbol + */ + function symbol() external view returns (string memory) { + return SYMBOL; + } + + /** + * @dev Returns an URI for a given token ID + * Throws if the token ID does not exist. May return an empty string. + * @param _tokenId uint256 ID of the token to query + */ + function tokenURI(uint256 _tokenId) public view returns (string memory) { + return Strings.strConcat( + tokenMetadataBaseURI, + Strings.uint2str(_tokenId) + ); + } + + /** + * @dev Gets the token ID at a given index of the tokens list of the requested owner + * @param _owner address owning the tokens list to be accessed + * @param _index uint256 representing the index to be accessed of the requested tokens list + * @return uint256 token ID at the given index of the tokens list owned by the requested address + */ + function tokenOfOwnerByIndex( + address _owner, + uint256 _index + ) + public + view + returns (uint256) + { + require(_index < balanceOf(_owner)); + return ownedTokens[_owner][_index]; + } + + /** + * @dev Gets the total amount of tokens stored by the contract + * @return uint256 representing the total amount of tokens + */ + function totalSupply() public view returns (uint256) { + return cards.length; + } + + /** + * @dev Gets the token ID at a given index of all the tokens in this contract + * Reverts if the index is greater or equal to the total number of tokens + * @param _index uint256 representing the index to be accessed of the tokens list + * @return uint256 token ID at the given index of the tokens list + */ + function tokenByIndex(uint256 _index) public view returns (uint256) { + require(_index < totalSupply()); + return _index; + } + + /** + * @dev Internal function to add a token ID to the list of a given address + * @param _to address representing the new owner of the given token ID + * @param _tokenId uint256 ID of the token to be added to the tokens list of the given address + */ + function addTokenTo(address _to, uint256 _tokenId) internal { + super.addTokenTo(_to, _tokenId); + uint256 length = ownedTokens[_to].length; + // EDITED: prevent overflow + require(length == uint32(length)); + ownedTokens[_to].push(uint40(_tokenId)); + + ownedTokensIndex[_tokenId] = uint32(length); + } + + // EDITED + // have to have in order to use array rather than mapping + function addNewTokenTo(address _to, uint256 _tokenId) internal { + super.addNewTokenTo(_to, _tokenId); + uint256 length = ownedTokens[_to].length; + // EDITED: prevent overflow + require(length == uint32(length)); + ownedTokens[_to].push(uint40(_tokenId)); + ownedTokensIndex.push(uint32(length)); + } + + /** + * @dev Internal function to remove a token ID from the list of a given address + * @param _from address representing the previous owner of the given token ID + * @param _tokenId uint256 ID of the token to be removed from the tokens list of the given address + */ + function removeTokenFrom(address _from, uint256 _tokenId) internal { + super.removeTokenFrom(_from, _tokenId); + + uint32 tokenIndex = ownedTokensIndex[_tokenId]; + uint256 lastTokenIndex = ownedTokens[_from].length.sub(1); + uint40 lastToken = ownedTokens[_from][lastTokenIndex]; + + ownedTokens[_from][tokenIndex] = lastToken; + ownedTokens[_from][lastTokenIndex] = 0; + // Note that this will handle single-element arrays. In that case, both tokenIndex and lastTokenIndex are going to + // be zero. Then we can make sure that we will remove _tokenId from the ownedTokens list since we are first swapping + // the lastToken to the first position, and then dropping the element placed in the last position of the list + + ownedTokens[_from].length--; + ownedTokensIndex[_tokenId] = 0; + ownedTokensIndex[lastToken] = tokenIndex; + } + + /** + * @dev Gets the balance of the specified address - overrriden from previous to save gas + * @param _owner address to query the balance of + * @return uint256 representing the amount owned by the passed address + */ + function balanceOf(address _owner) public view returns (uint256) { + return ownedTokens[_owner].length; + } + +} + +contract CardOwnershipTwo is ERC721Token { + + uint public burnCount; + + function getActiveCards() public view returns (uint) { + return totalSupply() - burnCount; + } + + /** + * @param to : the address to which the card will be transferred + * @param id : the id of the card to be transferred + */ + function transfer(address to, uint id) public payable onlyOwnerOf(id) { + require(isTradable(cards[id].proto)); + require(to != address(0)); + + _transfer(msg.sender, to, id); + } + + function _transfer(address from, address to, uint id) internal { + + clearApproval(from, id); + + removeTokenFrom(from, id); + + addTokenTo(to, id); + + emit Transfer(from, to, id); + } + + /** + * @param to : the address to which the cards will be transferred + * @param ids : the ids of the cards to be transferred + */ + function transferAll(address to, uint[] memory ids) public payable { + for (uint i = 0; i < ids.length; i++) { + transfer(to, ids[i]); + } + } + + /** + * @param proposed : the claimed owner of the cards + * @param ids : the ids of the cards to check + * @return whether proposed owns all of the cards + */ + function ownsAll(address proposed, uint[] memory ids) public view returns (bool) { + require(ids.length > 0); + for (uint i = 0; i < ids.length; i++) { + if (!owns(proposed, ids[i])) { + return false; + } + } + return true; + } + + /** + * @param proposed : the claimed owner of the card + * @param id : the id of the card to check + * @return whether proposed owns the card + */ + function owns(address proposed, uint id) public view returns (bool) { + return ownerOf(id) == proposed; + } + + function burn(uint id) public onlyOwnerOf(id) { + burnCount++; + _burn(msg.sender, id); + } + + /** + * @param ids : the indices of the tokens to burn + */ + function burnAll(uint[] memory ids) public { + for (uint i = 0; i < ids.length; i++){ + burn(ids[i]); + } + } + + /** + * @param to : the address to approve for transfer + * @param id : the index of the card to be approved + */ + function approve(address to, uint id) public { + require(isTradable(cards[id].proto)); + super.approve(to, id); + } + + /** + * @param to : the address to approve for transfer + * @param ids : the indices of the cards to be approved + */ + function approveAll(address to, uint[] memory ids) public { + for (uint i = 0; i < ids.length; i++) { + approve(to, ids[i]); + } + } + + /** + * @param to : the address to which the token should be transferred + * @param id : the index of the token to transfer + */ + function transferFrom(address from, address to, uint id) public { + require(isTradable(cards[id].proto)); + super.transferFrom(from, to, id); + } + + /** + * @param to : the address to which the tokens should be transferred + * @param ids : the indices of the tokens to transfer + */ + function transferAllFrom(address from, address to, uint[] memory ids) public { + for (uint i = 0; i < ids.length; i++) { + transferFrom(from, to, ids[i]); + } + } + + /** + * @return the number of cards which have been burned + */ + function getBurnCount() public view returns (uint) { + return burnCount; + } + +} + +contract CardIntegrationTwo is CardOwnershipTwo { + + address[] public packs; + + event CardCreated(uint indexed id, uint16 proto, uint16 purity, address owner); + + function addPack(address approved) public onlyGovernor { + packs.push(approved); + } + + modifier onlyApprovedPacks { + require(_isApprovedPack()); + _; + } + + function _isApprovedPack() private view returns (bool) { + for (uint i = 0; i < packs.length; i++) { + if (msg.sender == address(packs[i])) { + return true; + } + } + return false; + } + + function createCard(address owner, uint16 proto, uint16 purity) public whenNotPaused onlyApprovedPacks returns (uint) { + ProtoCard memory card = protos[proto]; + require(card.season == currentSeason); + if (card.rarity == Rarity.Mythic) { + uint64 limit; + bool exists; + (limit, exists) = getLimit(proto); + require(!exists || limit > 0); + limits[proto].limit--; + } + return _createCard(owner, proto, purity); + } + + function _createCard(address owner, uint16 proto, uint16 purity) internal returns (uint) { + Card memory card = Card({ + proto: proto, + purity: purity + }); + + uint id = cards.push(card) - 1; + + _mint(owner, id); + + emit CardCreated(id, proto, purity, owner); + + return id; + } + + /*function combineCards(uint[] ids) public whenNotPaused { + require(ids.length == 5); + require(ownsAll(msg.sender, ids)); + Card memory first = cards[ids[0]]; + uint16 proto = first.proto; + uint8 shine = _getShine(first.purity); + require(shine < shineLimit); + uint16 puritySum = first.purity - (shine * 1000); + burn(ids[0]); + for (uint i = 1; i < ids.length; i++) { + Card memory next = cards[ids[i]]; + require(next.proto == proto); + require(_getShine(next.purity) == shine); + puritySum += (next.purity - (shine * 1000)); + burn(ids[i]); + } + uint16 newPurity = uint16(((shine + 1) * 1000) + (puritySum / ids.length)); + _createCard(msg.sender, proto, newPurity); + }*/ + + + // PURITY NOTES + // currently, we only + // however, to protect rarity, you'll never be abl + // this is enforced by the restriction in the create-card function + // no cards above this point can be found in packs + + + +} + +contract PreviousInterface { + + function ownerOf(uint id) public view returns (address); + + function getCard(uint id) public view returns (uint16, uint16); + + function totalSupply() public view returns (uint); + + function burnCount() public view returns (uint); + +} + +contract CardMigration is CardIntegrationTwo { + + constructor(PreviousInterface previous) public { + old = previous; + } + + // use interface to lower deployment cost + PreviousInterface old; + + mapping(uint => bool) public migrated; + + function migrate(uint id) public { + + require(!migrated[id]); + + migrated[id] = true; + + address owner = old.ownerOf(id); + + uint16 proto; + uint16 purity; + + (proto, purity) = old.getCard(id); + + _createCard(owner, proto, purity); + } + + function migrateAll(uint[] memory ids) public { + + for (uint i = 0; i < ids.length; i++){ + migrate(ids[i]); + } + + } + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractScenario008.sol b/src/test/resources/soliditycode_v0.4.25/contractScenario008.sol new file mode 100644 index 00000000000..7336976e2b6 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractScenario008.sol @@ -0,0 +1,2016 @@ +//pragma solidity ^0.4.11; + + +/** + * @title Ownable + * @dev The Ownable contract has an owner address, and provides basic authorization control + * functions, this simplifies the implementation of "user permissions". + */ +contract Ownable { + address public owner; + + + /** + * @dev The Ownable constructor sets the original `owner` of the contract to the sender + * account. + */ + function Ownable() { + owner = msg.sender; + } + + + /** + * @dev Throws if called by any account other than the owner. + */ + modifier onlyOwner() { + require(msg.sender == owner); + _; + } + + + /** + * @dev Allows the current owner to transfer control of the contract to a newOwner. + * @param newOwner The address to transfer ownership to. + */ + function transferOwnership(address newOwner) onlyOwner { + if (newOwner != address(0)) { + owner = newOwner; + } + } + +} + + + +/// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens +/// @author Dieter Shirley (https://github.com/dete) +contract ERC721 { + // Required methods + function totalSupply() public view returns (uint256 total); + function balanceOf(address _owner) public view returns (uint256 balance); + function ownerOf(uint256 _tokenId) external view returns (address owner); + function approve(address _to, uint256 _tokenId) external; + function transfer(address _to, uint256 _tokenId) external; + function transferFrom(address _from, address _to, uint256 _tokenId) external; + + // Events + event Transfer(address from, address to, uint256 tokenId); + event Approval(address owner, address approved, uint256 tokenId); + + // Optional + // function name() public view returns (string name); + // function symbol() public view returns (string symbol); + // function tokensOfOwner(address _owner) external view returns (uint256[] tokenIds); + // function tokenMetadata(uint256 _tokenId, string _preferredTransport) public view returns (string infoUrl); + + // ERC-165 Compatibility (https://github.com/ethereum/EIPs/issues/165) + function supportsInterface(bytes4 _interfaceID) external view returns (bool); +} + + +// // Auction wrapper functions + + +// Auction wrapper functions + + + + + + + +/// @title SEKRETOOOO +contract GeneScienceInterface { + + function isGeneScience() public pure returns (bool){ + return true; + } + + /// @dev given genes of kitten 1 & 2, return a genetic combination - may have a random factor + /// @param genes1 genes of mom + /// @param genes2 genes of sire + /// @return the genes that are supposed to be passed down the child + function mixGenes(uint256 genes1, uint256 genes2, uint256 targetBlock) public pure returns (uint256){ + + return (genes1+genes2+targetBlock)/2; + + +} +} + + + + + + + +/// @title A facet of KittyCore that manages special access privileges. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. +contract KittyAccessControl { + // This facet controls access control for CryptoKitties. There are four roles managed here: + // + // - The CEO: The CEO can reassign other roles and change the addresses of our dependent smart + // contracts. It is also the only role that can unpause the smart contract. It is initially + // set to the address that created the smart contract in the KittyCore constructor. + // + // - The CFO: The CFO can withdraw funds from KittyCore and its auction contracts. + // + // - The COO: The COO can release gen0 kitties to auction, and mint promo cats. + // + // It should be noted that these roles are distinct without overlap in their access abilities, the + // abilities listed for each role above are exhaustive. In particular, while the CEO can assign any + // address to any role, the CEO address itself doesn't have the ability to act in those roles. This + // restriction is intentional so that we aren't tempted to use the CEO address frequently out of + // convenience. The less we use an address, the less likely it is that we somehow compromise the + // account. + + /// @dev Emited when contract is upgraded - See README.md for updgrade plan + event ContractUpgrade(address newContract); + + // The addresses of the accounts (or contracts) that can execute actions within each roles. + address public ceoAddress; + address public cfoAddress; + address public cooAddress; + + // @dev Keeps track whether the contract is paused. When that is true, most actions are blocked + bool public paused = false; + + /// @dev Access modifier for CEO-only functionality + modifier onlyCEO() { + require(msg.sender == ceoAddress); + _; + } + + /// @dev Access modifier for CFO-only functionality + modifier onlyCFO() { + require(msg.sender == cfoAddress); + _; + } + + /// @dev Access modifier for COO-only functionality + modifier onlyCOO() { + require(msg.sender == cooAddress); + _; + } + + modifier onlyCLevel() { + require( + msg.sender == cooAddress || + msg.sender == ceoAddress || + msg.sender == cfoAddress + ); + _; + } + + /// @dev Assigns a new address to act as the CEO. Only available to the current CEO. + /// @param _newCEO The address of the new CEO + function setCEO(address _newCEO) external onlyCEO { + require(_newCEO != address(0)); + + ceoAddress = _newCEO; + } + + /// @dev Assigns a new address to act as the CFO. Only available to the current CEO. + /// @param _newCFO The address of the new CFO + function setCFO(address _newCFO) external onlyCEO { + require(_newCFO != address(0)); + + cfoAddress = _newCFO; + } + + /// @dev Assigns a new address to act as the COO. Only available to the current CEO. + /// @param _newCOO The address of the new COO + function setCOO(address _newCOO) external onlyCEO { + require(_newCOO != address(0)); + + cooAddress = _newCOO; + } + + /*** Pausable functionality adapted from OpenZeppelin ***/ + + /// @dev Modifier to allow actions only when the contract IS NOT paused + modifier whenNotPaused() { + require(!paused); + _; + } + + /// @dev Modifier to allow actions only when the contract IS paused + modifier whenPaused { + require(paused); + _; + } + + /// @dev Called by any "C-level" role to pause the contract. Used only when + /// a bug or exploit is detected and we need to limit damage. + function pause() external onlyCLevel whenNotPaused { + paused = true; + } + + /// @dev Unpauses the smart contract. Can only be called by the CEO, since + /// one reason we may pause the contract is when CFO or COO accounts are + /// compromised. + /// @notice This is public rather than external so it can be called by + /// derived contracts. + function unpause() public onlyCEO whenPaused { + // can't unpause if contract was upgraded + paused = false; + } +} + + + + +/// @title Base contract for CryptoKitties. Holds all common structs, events and base variables. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. +contract KittyBase is KittyAccessControl { + /*** EVENTS ***/ + + /// @dev The Birth event is fired whenever a new kitten comes into existence. This obviously + /// includes any time a cat is created through the giveBirth method, but it is also called + /// when a new gen0 cat is created. + event Birth(address owner, uint256 kittyId, uint256 matronId, uint256 sireId, uint256 genes); + + /// @dev Transfer event as defined in current draft of ERC721. Emitted every time a kitten + /// ownership is assigned, including births. + event Transfer(address from, address to, uint256 tokenId); + + /*** DATA TYPES ***/ + + /// @dev The main Kitty struct. Every cat in CryptoKitties is represented by a copy + /// of this structure, so great care was taken to ensure that it fits neatly into + /// exactly two 256-bit words. Note that the order of the members in this structure + /// is important because of the byte-packing rules used by Ethereum. + /// Ref: http://solidity.readthedocs.io/en/develop/miscellaneous.html + struct Kitty { + // The Kitty's genetic code is packed into these 256-bits, the format is + // sooper-sekret! A cat's genes never change. + uint256 genes; + + // The timestamp from the block when this cat came into existence. + uint64 birthTime; + + // The minimum timestamp after which this cat can engage in breeding + // activities again. This same timestamp is used for the pregnancy + // timer (for matrons) as well as the siring cooldown. + uint64 cooldownEndBlock; + + // The ID of the parents of this kitty, set to 0 for gen0 cats. + // Note that using 32-bit unsigned integers limits us to a "mere" + // 4 billion cats. This number might seem small until you realize + // that Ethereum currently has a limit of about 500 million + // transactions per year! So, this definitely won't be a problem + // for several years (even as Ethereum learns to scale). + uint32 matronId; + uint32 sireId; + + // Set to the ID of the sire cat for matrons that are pregnant, + // zero otherwise. A non-zero value here is how we know a cat + // is pregnant. Used to retrieve the genetic material for the new + // kitten when the birth transpires. + uint32 siringWithId; + + // Set to the index in the cooldown array (see below) that represents + // the current cooldown duration for this Kitty. This starts at zero + // for gen0 cats, and is initialized to floor(generation/2) for others. + // Incremented by one for each successful breeding action, regardless + // of whether this cat is acting as matron or sire. + uint16 cooldownIndex; + + // The "generation number" of this cat. Cats minted by the CK contract + // for sale are called "gen0" and have a generation number of 0. The + // generation number of all other cats is the larger of the two generation + // numbers of their parents, plus one. + // (i.e. max(matron.generation, sire.generation) + 1) + uint16 generation; + } + + /*** CONSTANTS ***/ + + /// @dev A lookup table indicating the cooldown duration after any successful + /// breeding action, called "pregnancy time" for matrons and "siring cooldown" + /// for sires. Designed such that the cooldown roughly doubles each time a cat + /// is bred, encouraging owners not to just keep breeding the same cat over + /// and over again. Caps out at one week (a cat can breed an unbounded number + /// of times, and the maximum cooldown is always seven days). + uint32[14] public cooldowns = [ + uint32(1 minutes), + uint32(2 minutes), + uint32(5 minutes), + uint32(10 minutes), + uint32(30 minutes), + uint32(1 hours), + uint32(2 hours), + uint32(4 hours), + uint32(8 hours), + uint32(16 hours), + uint32(1 days), + uint32(2 days), + uint32(4 days), + uint32(7 days) + ]; + + // An approximation of currently how many seconds are in between blocks. + uint256 public secondsPerBlock = 15; + + /*** STORAGE ***/ + + /// @dev An array containing the Kitty struct for all Kitties in existence. The ID + /// of each cat is actually an index into this array. Note that ID 0 is a negacat, + /// the unKitty, the mythical beast that is the parent of all gen0 cats. A bizarre + /// creature that is both matron and sire... to itself! Has an invalid genetic code. + /// In other words, cat ID 0 is invalid... ;-) + Kitty[] kitties; + + /// @dev A mapping from cat IDs to the address that owns them. All cats have + /// some valid owner address, even gen0 cats are created with a non-zero owner. + mapping (uint256 => address) public kittyIndexToOwner; + + // @dev A mapping from owner address to count of tokens that address owns. + // Used internally inside balanceOf() to resolve ownership count. + mapping (address => uint256) ownershipTokenCount; + + /// @dev A mapping from KittyIDs to an address that has been approved to call + /// transferFrom(). Each Kitty can only have one approved address for transfer + /// at any time. A zero value means no approval is outstanding. + mapping (uint256 => address) public kittyIndexToApproved; + + /// @dev A mapping from KittyIDs to an address that has been approved to use + /// this Kitty for siring via breedWith(). Each Kitty can only have one approved + /// address for siring at any time. A zero value means no approval is outstanding. + mapping (uint256 => address) public sireAllowedToAddress; + + /// @dev The address of the ClockAuction contract that handles sales of Kitties. This + /// same contract handles both peer-to-peer sales as well as the gen0 sales which are + /// initiated every 15 minutes. + SaleClockAuction public saleAuction; + + /// @dev The address of a custom ClockAuction subclassed contract that handles siring + /// auctions. Needs to be separate from saleAuction because the actions taken on success + /// after a sales and siring auction are quite different. + SiringClockAuction public siringAuction; + + /// @dev Assigns ownership of a specific Kitty to an address. + function _transfer(address _from, address _to, uint256 _tokenId) internal { + // Since the number of kittens is capped to 2^32 we can't overflow this + ownershipTokenCount[_to]++; + // transfer ownership + kittyIndexToOwner[_tokenId] = _to; + // When creating new kittens _from is 0x0, but we can't account that address. + if (_from != address(0)) { + ownershipTokenCount[_from]--; + // once the kitten is transferred also clear sire allowances + delete sireAllowedToAddress[_tokenId]; + // clear any previously approved ownership exchange + delete kittyIndexToApproved[_tokenId]; + } + // Emit the transfer event. + Transfer(_from, _to, _tokenId); + } + + /// @dev An internal method that creates a new kitty and stores it. This + /// method doesn't do any checking and should only be called when the + /// input data is known to be valid. Will generate both a Birth event + /// and a Transfer event. + /// @param _matronId The kitty ID of the matron of this cat (zero for gen0) + /// @param _sireId The kitty ID of the sire of this cat (zero for gen0) + /// @param _generation The generation number of this cat, must be computed by caller. + /// @param _genes The kitty's genetic code. + /// @param _owner The inital owner of this cat, must be non-zero (except for the unKitty, ID 0) + function _createKitty( + uint256 _matronId, + uint256 _sireId, + uint256 _generation, + uint256 _genes, + address _owner + ) + internal + returns (uint) + { + // These requires are not strictly necessary, our calling code should make + // sure that these conditions are never broken. However! _createKitty() is already + // an expensive call (for storage), and it doesn't hurt to be especially careful + // to ensure our data structures are always valid. + require(_matronId == uint256(uint32(_matronId))); + require(_sireId == uint256(uint32(_sireId))); + require(_generation == uint256(uint16(_generation))); + + // New kitty starts with the same cooldown as parent gen/2 + uint16 cooldownIndex = uint16(_generation / 2); + if (cooldownIndex > 13) { + cooldownIndex = 13; + } + + Kitty memory _kitty = Kitty({ + genes: _genes, + birthTime: uint64(now), + cooldownEndBlock: 0, + matronId: uint32(_matronId), + sireId: uint32(_sireId), + siringWithId: 0, + cooldownIndex: cooldownIndex, + generation: uint16(_generation) + }); + uint256 newKittenId = kitties.push(_kitty) - 1; + + // It's probably never going to happen, 4 billion cats is A LOT, but + // let's just be 100% sure we never let this happen. + require(newKittenId == uint256(uint32(newKittenId))); + + // emit the birth event + Birth( + _owner, + newKittenId, + uint256(_kitty.matronId), + uint256(_kitty.sireId), + _kitty.genes + ); + + // This will assign ownership, and also emit the Transfer event as + // per ERC721 draft + _transfer(0, _owner, newKittenId); + + return newKittenId; + } + + // Any C-level can fix how many seconds per blocks are currently observed. + function setSecondsPerBlock(uint256 secs) external onlyCLevel { + require(secs < cooldowns[0]); + secondsPerBlock = secs; + } +} + + + + + +/// @title The external contract that is responsible for generating metadata for the kitties, +/// it has one function that will return the data as bytes. +contract ERC721Metadata { + /// @dev Given a token Id, returns a byte array that is supposed to be converted into string. + function getMetadata(uint256 _tokenId, string) public view returns (bytes32[4] buffer, uint256 count) { + if (_tokenId == 1) { + buffer[0] = "Hello World! :D"; + count = 15; + } else if (_tokenId == 2) { + buffer[0] = "I would definitely choose a medi"; + buffer[1] = "um length string."; + count = 49; + } else if (_tokenId == 3) { + buffer[0] = "Lorem ipsum dolor sit amet, mi e"; + buffer[1] = "st accumsan dapibus augue lorem,"; + buffer[2] = " tristique vestibulum id, libero"; + buffer[3] = " suscipit varius sapien aliquam."; + count = 128; + } + } +} + + +/// @title The facet of the CryptoKitties core contract that manages ownership, ERC-721 (draft) compliant. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev Ref: https://github.com/ethereum/EIPs/issues/721 +/// See the KittyCore contract documentation to understand how the various contract facets are arranged. +contract KittyOwnership is KittyBase, ERC721 { + + /// @notice Name and symbol of the non fungible token, as defined in ERC721. + string public constant name = "CryptoKitties"; + string public constant symbol = "CK"; + + // The contract that will return kitty metadata + ERC721Metadata public erc721Metadata; + + bytes4 constant InterfaceSignature_ERC165 = + bytes4(keccak256('supportsInterface(bytes4)')); + + bytes4 constant InterfaceSignature_ERC721 = + bytes4(keccak256('name()')) ^ + bytes4(keccak256('symbol()')) ^ + bytes4(keccak256('totalSupply()')) ^ + bytes4(keccak256('balanceOf(address)')) ^ + bytes4(keccak256('ownerOf(uint256)')) ^ + bytes4(keccak256('approve(address,uint256)')) ^ + bytes4(keccak256('transfer(address,uint256)')) ^ + bytes4(keccak256('transferFrom(address,address,uint256)')) ^ + bytes4(keccak256('tokensOfOwner(address)')) ^ + bytes4(keccak256('tokenMetadata(uint256,string)')); + + /// @notice Introspection interface as per ERC-165 (https://github.com/ethereum/EIPs/issues/165). + /// Returns true for any standardized interfaces implemented by this contract. We implement + /// ERC-165 (obviously!) and ERC-721. + function supportsInterface(bytes4 _interfaceID) external view returns (bool) + { + // DEBUG ONLY + //require((InterfaceSignature_ERC165 == 0x01ffc9a7) && (InterfaceSignature_ERC721 == 0x9a20483d)); + + return ((_interfaceID == InterfaceSignature_ERC165) || (_interfaceID == InterfaceSignature_ERC721)); + } + + /// @dev Set the address of the sibling contract that tracks metadata. + /// CEO only. + function setMetadataAddress(address _contractAddress) public onlyCEO { + erc721Metadata = ERC721Metadata(_contractAddress); + } + + // Internal utility functions: These functions all assume that their input arguments + // are valid. We leave it to public methods to sanitize their inputs and follow + // the required logic. + + /// @dev Checks if a given address is the current owner of a particular Kitty. + /// @param _claimant the address we are validating against. + /// @param _tokenId kitten id, only valid when > 0 + function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { + return kittyIndexToOwner[_tokenId] == _claimant; + } + + /// @dev Checks if a given address currently has transferApproval for a particular Kitty. + /// @param _claimant the address we are confirming kitten is approved for. + /// @param _tokenId kitten id, only valid when > 0 + function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) { + return kittyIndexToApproved[_tokenId] == _claimant; + } + + /// @dev Marks an address as being approved for transferFrom(), overwriting any previous + /// approval. Setting _approved to address(0) clears all transfer approval. + /// NOTE: _approve() does NOT send the Approval event. This is intentional because + /// _approve() and transferFrom() are used together for putting Kitties on auction, and + /// there is no value in spamming the log with Approval events in that case. + function _approve(uint256 _tokenId, address _approved) internal { + kittyIndexToApproved[_tokenId] = _approved; + } + + /// @notice Returns the number of Kitties owned by a specific address. + /// @param _owner The owner address to check. + /// @dev Required for ERC-721 compliance + function balanceOf(address _owner) public view returns (uint256 count) { + return ownershipTokenCount[_owner]; + } + + /// @notice Transfers a Kitty to another address. If transferring to a smart + /// contract be VERY CAREFUL to ensure that it is aware of ERC-721 (or + /// CryptoKitties specifically) or your Kitty may be lost forever. Seriously. + /// @param _to The address of the recipient, can be a user or contract. + /// @param _tokenId The ID of the Kitty to transfer. + /// @dev Required for ERC-721 compliance. + function transfer( + address _to, + uint256 _tokenId + ) + external + whenNotPaused + { + // Safety check to prevent against an unexpected 0x0 default. + require(_to != address(0)); + // Disallow transfers to this contract to prevent accidental misuse. + // The contract should never own any kitties (except very briefly + // after a gen0 cat is created and before it goes on auction). + require(_to != address(this)); + // Disallow transfers to the auction contracts to prevent accidental + // misuse. Auction contracts should only take ownership of kitties + // through the allow + transferFrom flow. + require(_to != address(saleAuction)); + require(_to != address(siringAuction)); + + // You can only send your own cat. + require(_owns(msg.sender, _tokenId)); + + // Reassign ownership, clear pending approvals, emit Transfer event. + _transfer(msg.sender, _to, _tokenId); + } + + /// @notice Grant another address the right to transfer a specific Kitty via + /// transferFrom(). This is the preferred flow for transfering NFTs to contracts. + /// @param _to The address to be granted transfer approval. Pass address(0) to + /// clear all approvals. + /// @param _tokenId The ID of the Kitty that can be transferred if this call succeeds. + /// @dev Required for ERC-721 compliance. + function approve( + address _to, + uint256 _tokenId + ) + external + whenNotPaused + { + // Only an owner can grant transfer approval. + require(_owns(msg.sender, _tokenId)); + + // Register the approval (replacing any previous approval). + _approve(_tokenId, _to); + + // Emit approval event. + Approval(msg.sender, _to, _tokenId); + } + + /// @notice Transfer a Kitty owned by another address, for which the calling address + /// has previously been granted transfer approval by the owner. + /// @param _from The address that owns the Kitty to be transfered. + /// @param _to The address that should take ownership of the Kitty. Can be any address, + /// including the caller. + /// @param _tokenId The ID of the Kitty to be transferred. + /// @dev Required for ERC-721 compliance. + function transferFrom( + address _from, + address _to, + uint256 _tokenId + ) + external + whenNotPaused + { + // Safety check to prevent against an unexpected 0x0 default. + require(_to != address(0)); + // Disallow transfers to this contract to prevent accidental misuse. + // The contract should never own any kitties (except very briefly + // after a gen0 cat is created and before it goes on auction). + require(_to != address(this)); + // Check for approval and valid ownership + require(_approvedFor(msg.sender, _tokenId)); + require(_owns(_from, _tokenId)); + + // Reassign ownership (also clears pending approvals and emits Transfer event). + _transfer(_from, _to, _tokenId); + } + + /// @notice Returns the total number of Kitties currently in existence. + /// @dev Required for ERC-721 compliance. + function totalSupply() public view returns (uint) { + return kitties.length - 1; + } + + /// @notice Returns the address currently assigned ownership of a given Kitty. + /// @dev Required for ERC-721 compliance. + function ownerOf(uint256 _tokenId) + external + view + returns (address owner) + { + owner = kittyIndexToOwner[_tokenId]; + + require(owner != address(0)); + } + + /// @notice Returns a list of all Kitty IDs assigned to an address. + /// @param _owner The owner whose Kitties we are interested in. + /// @dev This method MUST NEVER be called by smart contract code. First, it's fairly + /// expensive (it walks the entire Kitty array looking for cats belonging to owner), + /// but it also returns a dynamic array, which is only supported for web3 calls, and + /// not contract-to-contract calls. + function tokensOfOwner(address _owner) external view returns(uint256[] ownerTokens) { + uint256 tokenCount = balanceOf(_owner); + + if (tokenCount == 0) { + // Return an empty array + return new uint256[](0); + } else { + uint256[] memory result = new uint256[](tokenCount); + uint256 totalCats = totalSupply(); + uint256 resultIndex = 0; + + // We count on the fact that all cats have IDs starting at 1 and increasing + // sequentially up to the totalCat count. + uint256 catId; + + for (catId = 1; catId <= totalCats; catId++) { + if (kittyIndexToOwner[catId] == _owner) { + result[resultIndex] = catId; + resultIndex++; + } + } + + return result; + } + } + + /// @dev Adapted from memcpy() by @arachnid (Nick Johnson ) + /// This method is licenced under the Apache License. + /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol + function _memcpy(uint _dest, uint _src, uint _len) private view { + // Copy word-length chunks while possible + for(; _len >= 32; _len -= 32) { + assembly { + mstore(_dest, mload(_src)) + } + _dest += 32; + _src += 32; + } + + // Copy remaining bytes + uint256 mask = 256 ** (32 - _len) - 1; + assembly { + let srcpart := and(mload(_src), not(mask)) + let destpart := and(mload(_dest), mask) + mstore(_dest, or(destpart, srcpart)) + } + } + + /// @dev Adapted from toString(slice) by @arachnid (Nick Johnson ) + /// This method is licenced under the Apache License. + /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol + function _toString(bytes32[4] _rawBytes, uint256 _stringLength) private view returns (string) { + var outputString = new string(_stringLength); + uint256 outputPtr; + uint256 bytesPtr; + + assembly { + outputPtr := add(outputString, 32) + bytesPtr := _rawBytes + } + + _memcpy(outputPtr, bytesPtr, _stringLength); + + return outputString; + } + + /// @notice Returns a URI pointing to a metadata package for this token conforming to + /// ERC-721 (https://github.com/ethereum/EIPs/issues/721) + /// @param _tokenId The ID number of the Kitty whose metadata should be returned. + function tokenMetadata(uint256 _tokenId, string _preferredTransport) external view returns (string infoUrl) { + require(erc721Metadata != address(0)); + bytes32[4] memory buffer; + uint256 count; + (buffer, count) = erc721Metadata.getMetadata(_tokenId, _preferredTransport); + + return _toString(buffer, count); + } +} + + + +/// @title A facet of KittyCore that manages Kitty siring, gestation, and birth. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. +contract KittyBreeding is KittyOwnership { + + /// @dev The Pregnant event is fired when two cats successfully breed and the pregnancy + /// timer begins for the matron. + event Pregnant(address owner, uint256 matronId, uint256 sireId, uint256 cooldownEndBlock); + + /// @notice The minimum payment required to use breedWithAuto(). This fee goes towards + /// the gas cost paid by whatever calls giveBirth(), and can be dynamically updated by + /// the COO role as the gas price changes. + uint256 public autoBirthFee = 2 sun; + + // Keeps track of number of pregnant kitties. + uint256 public pregnantKitties; + + /// @dev The address of the sibling contract that is used to implement the sooper-sekret + /// genetic combination algorithm. + GeneScienceInterface public geneScience; + + /// @dev Update the address of the genetic contract, can only be called by the CEO. + /// @param _address An address of a GeneScience contract instance to be used from this point forward. + function setGeneScienceAddress(address _address) external onlyCEO { + GeneScienceInterface candidateContract = GeneScienceInterface(_address); + + // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 + require(candidateContract.isGeneScience()); + + // Set the new contract address + geneScience = candidateContract; + } + + /// @dev Checks that a given kitten is able to breed. Requires that the + /// current cooldown is finished (for sires) and also checks that there is + /// no pending pregnancy. + function _isReadyToBreed(Kitty _kit) internal view returns (bool) { + // In addition to checking the cooldownEndBlock, we also need to check to see if + // the cat has a pending birth; there can be some period of time between the end + // of the pregnacy timer and the birth event. + return (_kit.siringWithId == 0) && (_kit.cooldownEndBlock <= uint64(block.number)); + } + + /// @dev Check if a sire has authorized breeding with this matron. True if both sire + /// and matron have the same owner, or if the sire has given siring permission to + /// the matron's owner (via approveSiring()). + function _isSiringPermitted(uint256 _sireId, uint256 _matronId) internal view returns (bool) { + address matronOwner = kittyIndexToOwner[_matronId]; + address sireOwner = kittyIndexToOwner[_sireId]; + + // Siring is okay if they have same owner, or if the matron's owner was given + // permission to breed with this sire. + return (matronOwner == sireOwner || sireAllowedToAddress[_sireId] == matronOwner); + } + + /// @dev Set the cooldownEndTime for the given Kitty, based on its current cooldownIndex. + /// Also increments the cooldownIndex (unless it has hit the cap). + /// @param _kitten A reference to the Kitty in storage which needs its timer started. + function _triggerCooldown(Kitty storage _kitten) internal { + // Compute an estimation of the cooldown time in blocks (based on current cooldownIndex). + _kitten.cooldownEndBlock = uint64((cooldowns[_kitten.cooldownIndex]/secondsPerBlock) + block.number); + + // Increment the breeding count, clamping it at 13, which is the length of the + // cooldowns array. We could check the array size dynamically, but hard-coding + // this as a constant saves gas. Yay, Solidity! + if (_kitten.cooldownIndex < 13) { + _kitten.cooldownIndex += 1; + } + } + + /// @notice Grants approval to another user to sire with one of your Kitties. + /// @param _addr The address that will be able to sire with your Kitty. Set to + /// address(0) to clear all siring approvals for this Kitty. + /// @param _sireId A Kitty that you own that _addr will now be able to sire with. + function approveSiring(address _addr, uint256 _sireId) + external + whenNotPaused + { + require(_owns(msg.sender, _sireId)); + sireAllowedToAddress[_sireId] = _addr; + } + + /// @dev Updates the minimum payment required for calling giveBirthAuto(). Can only + /// be called by the COO address. (This fee is used to offset the gas cost incurred + /// by the autobirth daemon). + function setAutoBirthFee(uint256 val) external onlyCOO { + autoBirthFee = val; + } + + /// @dev Checks to see if a given Kitty is pregnant and (if so) if the gestation + /// period has passed. + function _isReadyToGiveBirth(Kitty _matron) private view returns (bool) { + return (_matron.siringWithId != 0) && (_matron.cooldownEndBlock <= uint64(block.number)); + } + + /// @notice Checks that a given kitten is able to breed (i.e. it is not pregnant or + /// in the middle of a siring cooldown). + /// @param _kittyId reference the id of the kitten, any user can inquire about it + function isReadyToBreed(uint256 _kittyId) + public + view + returns (bool) + { + require(_kittyId > 0); + Kitty storage kit = kitties[_kittyId]; + return _isReadyToBreed(kit); + } + + /// @dev Checks whether a kitty is currently pregnant. + /// @param _kittyId reference the id of the kitten, any user can inquire about it + function isPregnant(uint256 _kittyId) + public + view + returns (bool) + { + require(_kittyId > 0); + // A kitty is pregnant if and only if this field is set + return kitties[_kittyId].siringWithId != 0; + } + + /// @dev Internal check to see if a given sire and matron are a valid mating pair. DOES NOT + /// check ownership permissions (that is up to the caller). + /// @param _matron A reference to the Kitty struct of the potential matron. + /// @param _matronId The matron's ID. + /// @param _sire A reference to the Kitty struct of the potential sire. + /// @param _sireId The sire's ID + function _isValidMatingPair( + Kitty storage _matron, + uint256 _matronId, + Kitty storage _sire, + uint256 _sireId + ) + private + view + returns(bool) + { + // A Kitty can't breed with itself! + if (_matronId == _sireId) { + return false; + } + + // Kitties can't breed with their parents. + if (_matron.matronId == _sireId || _matron.sireId == _sireId) { + return false; + } + if (_sire.matronId == _matronId || _sire.sireId == _matronId) { + return false; + } + + // We can short circuit the sibling check (below) if either cat is + // gen zero (has a matron ID of zero). + if (_sire.matronId == 0 || _matron.matronId == 0) { + return true; + } + + // Kitties can't breed with full or half siblings. + if (_sire.matronId == _matron.matronId || _sire.matronId == _matron.sireId) { + return false; + } + if (_sire.sireId == _matron.matronId || _sire.sireId == _matron.sireId) { + return false; + } + + // Everything seems cool! Let's get DTF. + return true; + } + + /// @dev Internal check to see if a given sire and matron are a valid mating pair for + /// breeding via auction (i.e. skips ownership and siring approval checks). + function _canBreedWithViaAuction(uint256 _matronId, uint256 _sireId) + internal + view + returns (bool) + { + Kitty storage matron = kitties[_matronId]; + Kitty storage sire = kitties[_sireId]; + return _isValidMatingPair(matron, _matronId, sire, _sireId); + } + + /// @notice Checks to see if two cats can breed together, including checks for + /// ownership and siring approvals. Does NOT check that both cats are ready for + /// breeding (i.e. breedWith could still fail until the cooldowns are finished). + /// TODO: Shouldn't this check pregnancy and cooldowns?!? + /// @param _matronId The ID of the proposed matron. + /// @param _sireId The ID of the proposed sire. + function canBreedWith(uint256 _matronId, uint256 _sireId) + external + view + returns(bool) + { + require(_matronId > 0); + require(_sireId > 0); + Kitty storage matron = kitties[_matronId]; + Kitty storage sire = kitties[_sireId]; + return _isValidMatingPair(matron, _matronId, sire, _sireId) && + _isSiringPermitted(_sireId, _matronId); + } + + /// @dev Internal utility function to initiate breeding, assumes that all breeding + /// requirements have been checked. + function _breedWith(uint256 _matronId, uint256 _sireId) internal { + // Grab a reference to the Kitties from storage. + Kitty storage sire = kitties[_sireId]; + Kitty storage matron = kitties[_matronId]; + + // Mark the matron as pregnant, keeping track of who the sire is. + matron.siringWithId = uint32(_sireId); + + // Trigger the cooldown for both parents. + _triggerCooldown(sire); + _triggerCooldown(matron); + + // Clear siring permission for both parents. This may not be strictly necessary + // but it's likely to avoid confusion! + delete sireAllowedToAddress[_matronId]; + delete sireAllowedToAddress[_sireId]; + + // Every time a kitty gets pregnant, counter is incremented. + pregnantKitties++; + + // Emit the pregnancy event. + Pregnant(kittyIndexToOwner[_matronId], _matronId, _sireId, matron.cooldownEndBlock); + } + + /// @notice Breed a Kitty you own (as matron) with a sire that you own, or for which you + /// have previously been given Siring approval. Will either make your cat pregnant, or will + /// fail entirely. Requires a pre-payment of the fee given out to the first caller of giveBirth() + /// @param _matronId The ID of the Kitty acting as matron (will end up pregnant if successful) + /// @param _sireId The ID of the Kitty acting as sire (will begin its siring cooldown if successful) + function breedWithAuto(uint256 _matronId, uint256 _sireId) + external + payable + whenNotPaused + { + // Checks for payment. + require(msg.value >= autoBirthFee); + + // Caller must own the matron. + require(_owns(msg.sender, _matronId)); + + // Neither sire nor matron are allowed to be on auction during a normal + // breeding operation, but we don't need to check that explicitly. + // For matron: The caller of this function can't be the owner of the matron + // because the owner of a Kitty on auction is the auction house, and the + // auction house will never call breedWith(). + // For sire: Similarly, a sire on auction will be owned by the auction house + // and the act of transferring ownership will have cleared any oustanding + // siring approval. + // Thus we don't need to spend gas explicitly checking to see if either cat + // is on auction. + + // Check that matron and sire are both owned by caller, or that the sire + // has given siring permission to caller (i.e. matron's owner). + // Will fail for _sireId = 0 + require(_isSiringPermitted(_sireId, _matronId)); + + // Grab a reference to the potential matron + Kitty storage matron = kitties[_matronId]; + + // Make sure matron isn't pregnant, or in the middle of a siring cooldown + require(_isReadyToBreed(matron)); + + // Grab a reference to the potential sire + Kitty storage sire = kitties[_sireId]; + + // Make sure sire isn't pregnant, or in the middle of a siring cooldown + require(_isReadyToBreed(sire)); + + // Test that these cats are a valid mating pair. + require(_isValidMatingPair( + matron, + _matronId, + sire, + _sireId + )); + + // All checks passed, kitty gets pregnant! + _breedWith(_matronId, _sireId); + } + + /// @notice Have a pregnant Kitty give birth! + /// @param _matronId A Kitty ready to give birth. + /// @return The Kitty ID of the new kitten. + /// @dev Looks at a given Kitty and, if pregnant and if the gestation period has passed, + /// combines the genes of the two parents to create a new kitten. The new Kitty is assigned + /// to the current owner of the matron. Upon successful completion, both the matron and the + /// new kitten will be ready to breed again. Note that anyone can call this function (if they + /// are willing to pay the gas!), but the new kitten always goes to the mother's owner. + function giveBirth(uint256 _matronId) + external + whenNotPaused + returns(uint256) + { + // Grab a reference to the matron in storage. + Kitty storage matron = kitties[_matronId]; + + // Check that the matron is a valid cat. + require(matron.birthTime != 0); + + // Check that the matron is pregnant, and that its time has come! + require(_isReadyToGiveBirth(matron)); + + // Grab a reference to the sire in storage. + uint256 sireId = matron.siringWithId; + Kitty storage sire = kitties[sireId]; + + // Determine the higher generation number of the two parents + uint16 parentGen = matron.generation; + if (sire.generation > matron.generation) { + parentGen = sire.generation; + } + + // Call the sooper-sekret gene mixing operation. + uint256 childGenes = geneScience.mixGenes(matron.genes, sire.genes, matron.cooldownEndBlock - 1); + + // Make the new kitten! + address owner = kittyIndexToOwner[_matronId]; + uint256 kittenId = _createKitty(_matronId, matron.siringWithId, parentGen + 1, childGenes, owner); + + // Clear the reference to sire from the matron (REQUIRED! Having siringWithId + // set is what marks a matron as being pregnant.) + delete matron.siringWithId; + + // Every time a kitty gives birth counter is decremented. + pregnantKitties--; + + // Send the balance fee to the person who made birth happen. + msg.sender.send(autoBirthFee); + + // return the new kitten's ID + return kittenId; + } +} + + + + + + + + + + +/// @title Auction Core +/// @dev Contains models, variables, and internal methods for the auction. +/// @notice We omit a fallback function to prevent accidental sends to this contract. +contract ClockAuctionBase { + + // Represents an auction on an NFT + struct Auction { + // Current owner of NFT + address seller; + // Price (in wei) at beginning of auction + uint128 startingPrice; + // Price (in wei) at end of auction + uint128 endingPrice; + // Duration (in seconds) of auction + uint64 duration; + // Time when auction started + // NOTE: 0 if this auction has been concluded + uint64 startedAt; + } + + // Reference to contract tracking NFT ownership + ERC721 public nonFungibleContract; + + // Cut owner takes on each auction, measured in basis points (1/100 of a percent). + // Values 0-10,000 map to 0%-100% + uint256 public ownerCut; + + // Map from token ID to their corresponding auction. + mapping (uint256 => Auction) tokenIdToAuction; + + event AuctionCreated(uint256 tokenId, uint256 startingPrice, uint256 endingPrice, uint256 duration); + event AuctionSuccessful(uint256 tokenId, uint256 totalPrice, address winner); + event AuctionCancelled(uint256 tokenId); + + /// @dev Returns true if the claimant owns the token. + /// @param _claimant - Address claiming to own the token. + /// @param _tokenId - ID of token whose ownership to verify. + function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { + return (nonFungibleContract.ownerOf(_tokenId) == _claimant); + } + + /// @dev Escrows the NFT, assigning ownership to this contract. + /// Throws if the escrow fails. + /// @param _owner - Current owner address of token to escrow. + /// @param _tokenId - ID of token whose approval to verify. + function _escrow(address _owner, uint256 _tokenId) internal { + // it will throw if transfer fails + nonFungibleContract.transferFrom(_owner, this, _tokenId); + } + + /// @dev Transfers an NFT owned by this contract to another address. + /// Returns true if the transfer succeeds. + /// @param _receiver - Address to transfer NFT to. + /// @param _tokenId - ID of token to transfer. + function _transfer(address _receiver, uint256 _tokenId) internal { + // it will throw if transfer fails + nonFungibleContract.transfer(_receiver, _tokenId); + } + + /// @dev Adds an auction to the list of open auctions. Also fires the + /// AuctionCreated event. + /// @param _tokenId The ID of the token to be put on auction. + /// @param _auction Auction to add. + function _addAuction(uint256 _tokenId, Auction _auction) internal { + // Require that all auctions have a duration of + // at least one minute. (Keeps our math from getting hairy!) + require(_auction.duration >= 1 minutes); + + tokenIdToAuction[_tokenId] = _auction; + + AuctionCreated( + uint256(_tokenId), + uint256(_auction.startingPrice), + uint256(_auction.endingPrice), + uint256(_auction.duration) + ); + } + + /// @dev Cancels an auction unconditionally. + function _cancelAuction(uint256 _tokenId, address _seller) internal { + _removeAuction(_tokenId); + _transfer(_seller, _tokenId); + AuctionCancelled(_tokenId); + } + + /// @dev Computes the price and transfers winnings. + /// Does NOT transfer ownership of token. + function _bid(uint256 _tokenId, uint256 _bidAmount) + internal + returns (uint256) + { + // Get a reference to the auction struct + Auction storage auction = tokenIdToAuction[_tokenId]; + + // Explicitly check that this auction is currently live. + // (Because of how Ethereum mappings work, we can't just count + // on the lookup above failing. An invalid _tokenId will just + // return an auction object that is all zeros.) + require(_isOnAuction(auction)); + + // Check that the bid is greater than or equal to the current price + uint256 price = _currentPrice(auction); + require(_bidAmount >= price); + + // Grab a reference to the seller before the auction struct + // gets deleted. + address seller = auction.seller; + + // The bid is good! Remove the auction before sending the fees + // to the sender so we can't have a reentrancy attack. + _removeAuction(_tokenId); + + // Transfer proceeds to seller (if there are any!) + if (price > 0) { + // Calculate the auctioneer's cut. + // (NOTE: _computeCut() is guaranteed to return a + // value <= price, so this subtraction can't go negative.) + uint256 auctioneerCut = _computeCut(price); + uint256 sellerProceeds = price - auctioneerCut; + + // NOTE: Doing a transfer() in the middle of a complex + // method like this is generally discouraged because of + // reentrancy attacks and DoS attacks if the seller is + // a contract with an invalid fallback function. We explicitly + // guard against reentrancy attacks by removing the auction + // before calling transfer(), and the only thing the seller + // can DoS is the sale of their own asset! (And if it's an + // accident, they can call cancelAuction(). ) + seller.transfer(sellerProceeds); + } + + // Calculate any excess funds included with the bid. If the excess + // is anything worth worrying about, transfer it back to bidder. + // NOTE: We checked above that the bid amount is greater than or + // equal to the price so this cannot underflow. + uint256 bidExcess = _bidAmount - price; + + // Return the funds. Similar to the previous transfer, this is + // not susceptible to a re-entry attack because the auction is + // removed before any transfers occur. + msg.sender.transfer(bidExcess); + + // Tell the world! + AuctionSuccessful(_tokenId, price, msg.sender); + + return price; + } + + /// @dev Removes an auction from the list of open auctions. + /// @param _tokenId - ID of NFT on auction. + function _removeAuction(uint256 _tokenId) internal { + delete tokenIdToAuction[_tokenId]; + } + + /// @dev Returns true if the NFT is on auction. + /// @param _auction - Auction to check. + function _isOnAuction(Auction storage _auction) internal view returns (bool) { + return (_auction.startedAt > 0); + } + + /// @dev Returns current price of an NFT on auction. Broken into two + /// functions (this one, that computes the duration from the auction + /// structure, and the other that does the price computation) so we + /// can easily test that the price computation works correctly. + function _currentPrice(Auction storage _auction) + internal + view + returns (uint256) + { + uint256 secondsPassed = 0; + + // A bit of insurance against negative values (or wraparound). + // Probably not necessary (since Ethereum guarnatees that the + // now variable doesn't ever go backwards). + if (now > _auction.startedAt) { + secondsPassed = now - _auction.startedAt; + } + + return _computeCurrentPrice( + _auction.startingPrice, + _auction.endingPrice, + _auction.duration, + secondsPassed + ); + } + + /// @dev Computes the current price of an auction. Factored out + /// from _currentPrice so we can run extensive unit tests. + /// When testing, make this function public and turn on + /// `Current price computation` test suite. + function _computeCurrentPrice( + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration, + uint256 _secondsPassed + ) + internal + pure + returns (uint256) + { + // NOTE: We don't use SafeMath (or similar) in this function because + // all of our public functions carefully cap the maximum values for + // time (at 64-bits) and currency (at 128-bits). _duration is + // also known to be non-zero (see the require() statement in + // _addAuction()) + if (_secondsPassed >= _duration) { + // We've reached the end of the dynamic pricing portion + // of the auction, just return the end price. + return _endingPrice; + } else { + // Starting price can be higher than ending price (and often is!), so + // this delta can be negative. + int256 totalPriceChange = int256(_endingPrice) - int256(_startingPrice); + + // This multiplication can't overflow, _secondsPassed will easily fit within + // 64-bits, and totalPriceChange will easily fit within 128-bits, their product + // will always fit within 256-bits. + int256 currentPriceChange = totalPriceChange * int256(_secondsPassed) / int256(_duration); + + // currentPriceChange can be negative, but if so, will have a magnitude + // less that _startingPrice. Thus, this result will always end up positive. + int256 currentPrice = int256(_startingPrice) + currentPriceChange; + + return uint256(currentPrice); + } + } + + /// @dev Computes owner's cut of a sale. + /// @param _price - Sale price of NFT. + function _computeCut(uint256 _price) internal view returns (uint256) { + // NOTE: We don't use SafeMath (or similar) in this function because + // all of our entry functions carefully cap the maximum values for + // currency (at 128-bits), and ownerCut <= 10000 (see the require() + // statement in the ClockAuction constructor). The result of this + // function is always guaranteed to be <= _price. + return _price * ownerCut / 10000; + } + +} + + + + + + + +/** + * @title Pausable + * @dev Base contract which allows children to implement an emergency stop mechanism. + */ +contract Pausable is Ownable { + event Pause(); + event Unpause(); + + bool public paused = false; + + + /** + * @dev modifier to allow actions only when the contract IS paused + */ + modifier whenNotPaused() { + require(!paused); + _; + } + + /** + * @dev modifier to allow actions only when the contract IS NOT paused + */ + modifier whenPaused { + require(paused); + _; + } + + /** + * @dev called by the owner to pause, triggers stopped state + */ + function pause() onlyOwner whenNotPaused returns (bool) { + paused = true; + Pause(); + return true; + } + + /** + * @dev called by the owner to unpause, returns to normal state + */ + function unpause() onlyOwner whenPaused returns (bool) { + paused = false; + Unpause(); + return true; + } +} + + +/// @title Clock auction for non-fungible tokens. +/// @notice We omit a fallback function to prevent accidental sends to this contract. +contract ClockAuction is Pausable, ClockAuctionBase { + + /// @dev The ERC-165 interface signature for ERC-721. + /// Ref: https://github.com/ethereum/EIPs/issues/165 + /// Ref: https://github.com/ethereum/EIPs/issues/721 + bytes4 constant InterfaceSignature_ERC721 = bytes4(0x9a20483d); + + /// @dev Constructor creates a reference to the NFT ownership contract + /// and verifies the owner cut is in the valid range. + /// @param _nftAddress - address of a deployed contract implementing + /// the Nonfungible Interface. + /// @param _cut - percent cut the owner takes on each auction, must be + /// between 0-10,000. + function ClockAuction(address _nftAddress, uint256 _cut) public { + require(_cut <= 10000); + ownerCut = _cut; + + ERC721 candidateContract = ERC721(_nftAddress); + require(candidateContract.supportsInterface(InterfaceSignature_ERC721)); + nonFungibleContract = candidateContract; + } + + /// @dev Remove all Ether from the contract, which is the owner's cuts + /// as well as any Ether sent directly to the contract address. + /// Always transfers to the NFT contract, but can be called either by + /// the owner or the NFT contract. + function withdrawBalance() external { + address nftAddress = address(nonFungibleContract); + + require( + msg.sender == owner || + msg.sender == nftAddress + ); + // We are using this boolean method to make sure that even if one fails it will still work + bool res = nftAddress.send(this.balance); + } + + /// @dev Creates and begins a new auction. + /// @param _tokenId - ID of token to auction, sender must be owner. + /// @param _startingPrice - Price of item (in wei) at beginning of auction. + /// @param _endingPrice - Price of item (in wei) at end of auction. + /// @param _duration - Length of time to move between starting + /// price and ending price (in seconds). + /// @param _seller - Seller, if not the message sender + function createAuction( + uint256 _tokenId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration, + address _seller + ) + external + whenNotPaused + { + // Sanity check that no inputs overflow how many bits we've allocated + // to store them in the auction struct. + require(_startingPrice == uint256(uint128(_startingPrice))); + require(_endingPrice == uint256(uint128(_endingPrice))); + require(_duration == uint256(uint64(_duration))); + + require(_owns(msg.sender, _tokenId)); + _escrow(msg.sender, _tokenId); + Auction memory auction = Auction( + _seller, + uint128(_startingPrice), + uint128(_endingPrice), + uint64(_duration), + uint64(now) + ); + _addAuction(_tokenId, auction); + } + + /// @dev Bids on an open auction, completing the auction and transferring + /// ownership of the NFT if enough Ether is supplied. + /// @param _tokenId - ID of token to bid on. + function bid(uint256 _tokenId) + external + payable + whenNotPaused + { + // _bid will throw if the bid or funds transfer fails + _bid(_tokenId, msg.value); + _transfer(msg.sender, _tokenId); + } + + /// @dev Cancels an auction that hasn't been won yet. + /// Returns the NFT to original owner. + /// @notice This is a state-modifying function that can + /// be called while the contract is paused. + /// @param _tokenId - ID of token on auction + function cancelAuction(uint256 _tokenId) + external + { + Auction storage auction = tokenIdToAuction[_tokenId]; + require(_isOnAuction(auction)); + address seller = auction.seller; + require(msg.sender == seller); + _cancelAuction(_tokenId, seller); + } + + /// @dev Cancels an auction when the contract is paused. + /// Only the owner may do this, and NFTs are returned to + /// the seller. This should only be used in emergencies. + /// @param _tokenId - ID of the NFT on auction to cancel. + function cancelAuctionWhenPaused(uint256 _tokenId) + whenPaused + onlyOwner + external + { + Auction storage auction = tokenIdToAuction[_tokenId]; + require(_isOnAuction(auction)); + _cancelAuction(_tokenId, auction.seller); + } + + /// @dev Returns auction info for an NFT on auction. + /// @param _tokenId - ID of NFT on auction. + function getAuction(uint256 _tokenId) + external + view + returns + ( + address seller, + uint256 startingPrice, + uint256 endingPrice, + uint256 duration, + uint256 startedAt + ) { + Auction storage auction = tokenIdToAuction[_tokenId]; + require(_isOnAuction(auction)); + return ( + auction.seller, + auction.startingPrice, + auction.endingPrice, + auction.duration, + auction.startedAt + ); + } + + /// @dev Returns the current price of an auction. + /// @param _tokenId - ID of the token price we are checking. + function getCurrentPrice(uint256 _tokenId) + external + view + returns (uint256) + { + Auction storage auction = tokenIdToAuction[_tokenId]; + require(_isOnAuction(auction)); + return _currentPrice(auction); + } + +} + + +/// @title Reverse auction modified for siring +/// @notice We omit a fallback function to prevent accidental sends to this contract. +contract SiringClockAuction is ClockAuction { + + // @dev Sanity check that allows us to ensure that we are pointing to the + // right auction in our setSiringAuctionAddress() call. + bool public isSiringClockAuction = true; + + // Delegate constructor + function SiringClockAuction(address _nftAddr, uint256 _cut) public + ClockAuction(_nftAddr, _cut) {} + + /// @dev Creates and begins a new auction. Since this function is wrapped, + /// require sender to be KittyCore contract. + /// @param _tokenId - ID of token to auction, sender must be owner. + /// @param _startingPrice - Price of item (in wei) at beginning of auction. + /// @param _endingPrice - Price of item (in wei) at end of auction. + /// @param _duration - Length of auction (in seconds). + /// @param _seller - Seller, if not the message sender + function createAuction( + uint256 _tokenId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration, + address _seller + ) + external + { + // Sanity check that no inputs overflow how many bits we've allocated + // to store them in the auction struct. + require(_startingPrice == uint256(uint128(_startingPrice))); + require(_endingPrice == uint256(uint128(_endingPrice))); + require(_duration == uint256(uint64(_duration))); + + require(msg.sender == address(nonFungibleContract)); + _escrow(_seller, _tokenId); + Auction memory auction = Auction( + _seller, + uint128(_startingPrice), + uint128(_endingPrice), + uint64(_duration), + uint64(now) + ); + _addAuction(_tokenId, auction); + } + + /// @dev Places a bid for siring. Requires the sender + /// is the KittyCore contract because all bid methods + /// should be wrapped. Also returns the kitty to the + /// seller rather than the winner. + function bid(uint256 _tokenId) + external + payable + { + require(msg.sender == address(nonFungibleContract)); + address seller = tokenIdToAuction[_tokenId].seller; + // _bid checks that token ID is valid and will throw if bid fails + _bid(_tokenId, msg.value); + // We transfer the kitty back to the seller, the winner will get + // the offspring + _transfer(seller, _tokenId); + } + +} + + + + + +/// @title Clock auction modified for sale of kitties +/// @notice We omit a fallback function to prevent accidental sends to this contract. +contract SaleClockAuction is ClockAuction { + + // @dev Sanity check that allows us to ensure that we are pointing to the + // right auction in our setSaleAuctionAddress() call. + bool public isSaleClockAuction = true; + + // Tracks last 5 sale price of gen0 kitty sales + uint256 public gen0SaleCount; + uint256[5] public lastGen0SalePrices; + + // Delegate constructor + function SaleClockAuction(address _nftAddr, uint256 _cut) public + ClockAuction(_nftAddr, _cut) {} + + /// @dev Creates and begins a new auction. + /// @param _tokenId - ID of token to auction, sender must be owner. + /// @param _startingPrice - Price of item (in wei) at beginning of auction. + /// @param _endingPrice - Price of item (in wei) at end of auction. + /// @param _duration - Length of auction (in seconds). + /// @param _seller - Seller, if not the message sender + function createAuction( + uint256 _tokenId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration, + address _seller + ) + external + { + // Sanity check that no inputs overflow how many bits we've allocated + // to store them in the auction struct. + require(_startingPrice == uint256(uint128(_startingPrice))); + require(_endingPrice == uint256(uint128(_endingPrice))); + require(_duration == uint256(uint64(_duration))); + + require(msg.sender == address(nonFungibleContract)); + _escrow(_seller, _tokenId); + Auction memory auction = Auction( + _seller, + uint128(_startingPrice), + uint128(_endingPrice), + uint64(_duration), + uint64(now) + ); + _addAuction(_tokenId, auction); + } + + /// @dev Updates lastSalePrice if seller is the nft contract + /// Otherwise, works the same as default bid method. + function bid(uint256 _tokenId) + external + payable + { + // _bid verifies token ID size + address seller = tokenIdToAuction[_tokenId].seller; + uint256 price = _bid(_tokenId, msg.value); + _transfer(msg.sender, _tokenId); + + // If not a gen0 auction, exit + if (seller == address(nonFungibleContract)) { + // Track gen0 sale prices + lastGen0SalePrices[gen0SaleCount % 5] = price; + gen0SaleCount++; + } + } + + function averageGen0SalePrice() external view returns (uint256) { + uint256 sum = 0; + for (uint256 i = 0; i < 5; i++) { + sum += lastGen0SalePrices[i]; + } + return sum / 5; + } + +} + + +/// @title Handles creating auctions for sale and siring of kitties. +/// This wrapper of ReverseAuction exists only so that users can create +/// auctions with only one transaction. +contract KittyAuction is KittyBreeding { + + // @notice The auction contract variables are defined in KittyBase to allow + // us to refer to them in KittyOwnership to prevent accidental transfers. + // `saleAuction` refers to the auction for gen0 and p2p sale of kitties. + // `siringAuction` refers to the auction for siring rights of kitties. + + /// @dev Sets the reference to the sale auction. + /// @param _address - Address of sale contract. + function setSaleAuctionAddress(address _address) external onlyCEO { + SaleClockAuction candidateContract = SaleClockAuction(_address); + + // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 + require(candidateContract.isSaleClockAuction()); + + // Set the new contract address + saleAuction = candidateContract; + } + + /// @dev Sets the reference to the siring auction. + /// @param _address - Address of siring contract. + function setSiringAuctionAddress(address _address) external onlyCEO { + SiringClockAuction candidateContract = SiringClockAuction(_address); + + // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 + require(candidateContract.isSiringClockAuction()); + + // Set the new contract address + siringAuction = candidateContract; + } + + /// @dev Put a kitty up for auction. + /// Does some ownership trickery to create auctions in one tx. + function createSaleAuction( + uint256 _kittyId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration + ) + external + whenNotPaused + { + // Auction contract checks input sizes + // If kitty is already on any auction, this will throw + // because it will be owned by the auction contract. + require(_owns(msg.sender, _kittyId)); + // Ensure the kitty is not pregnant to prevent the auction + // contract accidentally receiving ownership of the child. + // NOTE: the kitty IS allowed to be in a cooldown. + require(!isPregnant(_kittyId)); + _approve(_kittyId, saleAuction); + // Sale auction throws if inputs are invalid and clears + // transfer and sire approval after escrowing the kitty. + saleAuction.createAuction( + _kittyId, + _startingPrice, + _endingPrice, + _duration, + msg.sender + ); + } + + /// @dev Put a kitty up for auction to be sire. + /// Performs checks to ensure the kitty can be sired, then + /// delegates to reverse auction. + function createSiringAuction( + uint256 _kittyId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration + ) + external + whenNotPaused + { + // Auction contract checks input sizes + // If kitty is already on any auction, this will throw + // because it will be owned by the auction contract. + require(_owns(msg.sender, _kittyId)); + require(isReadyToBreed(_kittyId)); + _approve(_kittyId, siringAuction); + // Siring auction throws if inputs are invalid and clears + // transfer and sire approval after escrowing the kitty. + siringAuction.createAuction( + _kittyId, + _startingPrice, + _endingPrice, + _duration, + msg.sender + ); + } + + /// @dev Completes a siring auction by bidding. + /// Immediately breeds the winning matron with the sire on auction. + /// @param _sireId - ID of the sire on auction. + /// @param _matronId - ID of the matron owned by the bidder. + function bidOnSiringAuction( + uint256 _sireId, + uint256 _matronId + ) + external + payable + whenNotPaused + { + // Auction contract checks input sizes + require(_owns(msg.sender, _matronId)); + require(isReadyToBreed(_matronId)); + require(_canBreedWithViaAuction(_matronId, _sireId)); + + // Define the current price of the auction. + uint256 currentPrice = siringAuction.getCurrentPrice(_sireId); + require(msg.value >= currentPrice + autoBirthFee); + + // Siring auction will throw if the bid fails. + siringAuction.bid.value(msg.value - autoBirthFee)(_sireId); + _breedWith(uint32(_matronId), uint32(_sireId)); + } + + /// @dev Transfers the balance of the sale auction contract + /// to the KittyCore contract. We use two-step withdrawal to + /// prevent two transfer calls in the auction bid function. + function withdrawAuctionBalances() external onlyCLevel { + saleAuction.withdrawBalance(); + siringAuction.withdrawBalance(); + } +} + + +/// @title all functions related to creating kittens +contract KittyMinting is KittyAuction { + + // Limits the number of cats the contract owner can ever create. + uint256 public constant PROMO_CREATION_LIMIT = 5000; + uint256 public constant GEN0_CREATION_LIMIT = 45000; + + // Constants for gen0 auctions. + uint256 public constant GEN0_STARTING_PRICE = 10 sun; + uint256 public constant GEN0_AUCTION_DURATION = 1 days; + + // Counts the number of cats the contract owner has created. + uint256 public promoCreatedCount; + uint256 public gen0CreatedCount; + + /// @dev we can create promo kittens, up to a limit. Only callable by COO + /// @param _genes the encoded genes of the kitten to be created, any value is accepted + /// @param _owner the future owner of the created kittens. Default to contract COO + function createPromoKitty(uint256 _genes, address _owner) external onlyCOO { + address kittyOwner = _owner; + if (kittyOwner == address(0)) { + kittyOwner = cooAddress; + } + require(promoCreatedCount < PROMO_CREATION_LIMIT); + + promoCreatedCount++; + _createKitty(0, 0, 0, _genes, kittyOwner); + } + + /// @dev Creates a new gen0 kitty with the given genes and + /// creates an auction for it. + function createGen0Auction(uint256 _genes) external onlyCOO { + require(gen0CreatedCount < GEN0_CREATION_LIMIT); + + uint256 kittyId = _createKitty(0, 0, 0, _genes, address(this)); + _approve(kittyId, saleAuction); + + saleAuction.createAuction( + kittyId, + _computeNextGen0Price(), + 0, + GEN0_AUCTION_DURATION, + address(this) + ); + + gen0CreatedCount++; + } + + /// @dev Computes the next gen0 auction starting price, given + /// the average of the past 5 prices + 50%. + function _computeNextGen0Price() internal view returns (uint256) { + uint256 avePrice = saleAuction.averageGen0SalePrice(); + + // Sanity check to ensure we don't overflow arithmetic + require(avePrice == uint256(uint128(avePrice))); + + uint256 nextPrice = avePrice + (avePrice / 2); + + // We never auction for less than starting price + if (nextPrice < GEN0_STARTING_PRICE) { + nextPrice = GEN0_STARTING_PRICE; + } + + return nextPrice; + } +} + + +/// @title CryptoKitties: Collectible, breedable, and oh-so-adorable cats on the Ethereum blockchain. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev The main CryptoKitties contract, keeps track of kittens so they don't wander around and get lost. +contract KittyCore is KittyMinting { + + // This is the main CryptoKitties contract. In order to keep our code seperated into logical sections, + // we've broken it up in two ways. First, we have several seperately-instantiated sibling contracts + // that handle auctions and our super-top-secret genetic combination algorithm. The auctions are + // seperate since their logic is somewhat complex and there's always a risk of subtle bugs. By keeping + // them in their own contracts, we can upgrade them without disrupting the main contract that tracks + // kitty ownership. The genetic combination algorithm is kept seperate so we can open-source all of + // the rest of our code without making it _too_ easy for folks to figure out how the genetics work. + // Don't worry, I'm sure someone will reverse engineer it soon enough! + // + // Secondly, we break the core contract into multiple files using inheritence, one for each major + // facet of functionality of CK. This allows us to keep related code bundled together while still + // avoiding a single giant file with everything in it. The breakdown is as follows: + // + // - KittyBase: This is where we define the most fundamental code shared throughout the core + // functionality. This includes our main data storage, constants and data types, plus + // internal functions for managing these items. + // + // - KittyAccessControl: This contract manages the various addresses and constraints for operations + // that can be executed only by specific roles. Namely CEO, CFO and COO. + // + // - KittyOwnership: This provides the methods required for basic non-fungible token + // transactions, following the draft ERC-721 spec (https://github.com/ethereum/EIPs/issues/721). + // + // - KittyBreeding: This file contains the methods necessary to breed cats together, including + // keeping track of siring offers, and relies on an external genetic combination contract. + // + // - KittyAuctions: Here we have the public methods for auctioning or bidding on cats or siring + // services. The actual auction functionality is handled in two sibling contracts (one + // for sales and one for siring), while auction creation and bidding is mostly mediated + // through this facet of the core contract. + // + // - KittyMinting: This final facet contains the functionality we use for creating new gen0 cats. + // We can make up to 5000 "promo" cats that can be given away (especially important when + // the community is new), and all others can only be created and then immediately put up + // for auction via an algorithmically determined starting price. Regardless of how they + // are created, there is a hard limit of 50k gen0 cats. After that, it's all up to the + // community to breed, breed, breed! + + // Set in case the core contract is broken and an upgrade is required + address public newContractAddress; + + /// @notice Creates the main CryptoKitties smart contract instance. + function KittyCore() public { + // Starts paused. + paused = true; + + // the creator of the contract is the initial CEO + ceoAddress = msg.sender; + + // the creator of the contract is also the initial COO + cooAddress = msg.sender; + + // start with the mythical kitten 0 - so we don't have generation-0 parent issues + _createKitty(0, 0, 0, uint256(-1), address(0)); + } + + /// @dev Used to mark the smart contract as upgraded, in case there is a serious + /// breaking bug. This method does nothing but keep track of the new contract and + /// emit a message indicating that the new address is set. It's up to clients of this + /// contract to update to the new contract address in that case. (This contract will + /// be paused indefinitely if such an upgrade takes place.) + /// @param _v2Address new address + function setNewAddress(address _v2Address) external onlyCEO whenPaused { + // See README.md for updgrade plan + newContractAddress = _v2Address; + ContractUpgrade(_v2Address); + } + + /// @notice No tipping! + /// @dev Reject all Ether from being sent here, unless it's from one of the + /// two auction contracts. (Hopefully, we can prevent user accidents.) + function() external payable { + require( + msg.sender == address(saleAuction) || + msg.sender == address(siringAuction) + ); + } + + /// @notice Returns all the relevant information about a specific kitty. + /// @param _id The ID of the kitty of interest. + function getKitty(uint256 _id) + external + view + returns ( + bool isGestating, + bool isReady, + uint256 cooldownIndex, + uint256 nextActionAt, + uint256 siringWithId, + uint256 birthTime, + uint256 matronId, + uint256 sireId, + uint256 generation, + uint256 genes + ) { + Kitty storage kit = kitties[_id]; + + // if this variable is 0 then it's not gestating + isGestating = (kit.siringWithId != 0); + isReady = (kit.cooldownEndBlock <= block.number); + cooldownIndex = uint256(kit.cooldownIndex); + nextActionAt = uint256(kit.cooldownEndBlock); + siringWithId = uint256(kit.siringWithId); + birthTime = uint256(kit.birthTime); + matronId = uint256(kit.matronId); + sireId = uint256(kit.sireId); + generation = uint256(kit.generation); + genes = kit.genes; + } + + /// @dev Override unpause so it requires all external contract addresses + /// to be set before contract can be unpaused. Also, we can't have + /// newContractAddress set either, because then the contract was upgraded. + /// @notice This is public rather than external so we can call super.unpause + /// without using an expensive CALL. + function unpause() public onlyCEO whenPaused { + require(saleAuction != address(0)); + require(siringAuction != address(0)); + require(geneScience != address(0)); + require(newContractAddress == address(0)); + + // Actually unpause the contract. + super.unpause(); + } + + // @dev Allows the CFO to capture the balance available to the contract. + function withdrawBalance() external onlyCFO { + uint256 balance = this.balance; + // Subtract all the currently pregnant kittens we have, plus 1 of margin. + uint256 subtractFees = (pregnantKitties + 1) * autoBirthFee; + + if (balance > subtractFees) { + cfoAddress.send(balance - subtractFees); + } + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractScenario009.sol b/src/test/resources/soliditycode_v0.4.25/contractScenario009.sol new file mode 100644 index 00000000000..215c671848e --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractScenario009.sol @@ -0,0 +1,51 @@ +//pragma solidity ^0.4.0; + +library Set { + // We define a new struct datatype that will be used to + // hold its data in the calling contract. + struct Data { mapping(uint => bool) flags; } + + // Note that the first parameter is of type "storage + // reference" and thus only its storage address and not + // its contents is passed as part of the call. This is a + // special feature of library functions. It is idiomatic + // to call the first parameter 'self', if the function can + // be seen as a method of that object. + function insert(Data storage self, uint value) + returns (bool) + { + if (self.flags[value]) + return false; // already there + self.flags[value] = true; + return true; + } + + function remove(Data storage self, uint value) + returns (bool) + { + if (!self.flags[value]) + return false; // not there + self.flags[value] = false; + return true; + } + + function contains(Data storage self, uint value) + returns (bool) + { + return self.flags[value]; + } +} + + +contract C { + Set.Data knownValues; + + function register(uint value) { + // The library functions can be called without a + // specific instance of the library, since the + // "instance" will be the current contract. + if (!Set.insert(knownValues, value)) + throw; + } + // In this contract, we can also directly access knownValues.flags, if we want. +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractScenario010.sol b/src/test/resources/soliditycode_v0.4.25/contractScenario010.sol new file mode 100644 index 00000000000..f665ea9686e --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractScenario010.sol @@ -0,0 +1,107 @@ +//pragma solidity ^0.4.11; + +contract TRON_ERC721 { + //name + function name() view public returns (string memory name){ + return "Tron ERC721 Token"; + } + //symbol + function symbol() view public returns (string memory symbol){ + return "T721T"; + } + + //totalSupply + + function totalSupply() view public returns (uint256 supply){ + uint256 totalSupply = 1000000000000; + return totalSupply; + } + + mapping(address => uint) private balances; + function balanceOf(address _owner) view public returns (uint balance) + { + return balances[_owner]; + } + + + mapping(uint256 => address) private tokenOwners; + mapping(uint256 => bool) private tokenExists; + function ownerOf(uint256 _tokenId) view public returns (address owner) { + require(tokenExists[_tokenId]); + return tokenOwners[_tokenId]; + } + + + mapping(address => mapping (address => uint256)) allowed; + function approve(address _to, uint256 _tokenId) public{ + require(msg.sender == ownerOf(_tokenId)); + require(msg.sender != _to); + allowed[msg.sender][_to] = _tokenId; + emit Approval(msg.sender, _to, _tokenId); + } + + + function takeOwnership(uint256 _tokenId) public { + require(tokenExists[_tokenId]); + address oldOwner = ownerOf(_tokenId); + address newOwner = msg.sender; + require(newOwner != oldOwner); + require(allowed[oldOwner][newOwner] == _tokenId); + balances[oldOwner] -= 1; + tokenOwners[_tokenId] = newOwner; + balances[newOwner] += 1; + emit Transfer(oldOwner, newOwner, _tokenId); + } + + + mapping(address => mapping(uint256 => uint256)) private ownerTokens; + function removeFromTokenList(address owner, uint256 _tokenId) private { + for(uint256 i = 0;ownerTokens[owner][i] != _tokenId;i++){ + ownerTokens[owner][i] = 0; + } + } + + function transfer(address _to, uint256 _tokenId) public{ + address currentOwner = msg.sender; + address newOwner = _to; + require(tokenExists[_tokenId]); + require(currentOwner == ownerOf(_tokenId)); + require(currentOwner != newOwner); + require(newOwner != address(0)); + address oldOwner =currentOwner; + removeFromTokenList(oldOwner,_tokenId); + balances[oldOwner] -= 1; + tokenOwners[_tokenId] = newOwner; + balances[newOwner] += 1; + emit Transfer(oldOwner, newOwner, _tokenId); + } + + function transferFrom(address _from,address _to, uint256 _tokenId) public{ + address currentOwner = _from; + address newOwner = _to; + require(tokenExists[_tokenId]); + require(currentOwner == ownerOf(_tokenId)); + require(currentOwner != newOwner); + require(newOwner != address(0)); + address oldOwner =currentOwner; + removeFromTokenList(oldOwner,_tokenId); + balances[oldOwner] -= 1; + tokenOwners[_tokenId] = newOwner; + balances[newOwner] += 1; + emit Transfer(oldOwner, newOwner, _tokenId); + } + + + function tokenOfOwnerByIndex(address _owner, uint256 _index) view public returns (uint tokenId){ + return ownerTokens[_owner][_index]; + } + + + mapping(uint256 => string) tokenLinks; + function tokenMetadata(uint256 _tokenId) view public returns (string memory infoUrl) { + return tokenLinks[_tokenId]; + } + // Events + event Transfer(address indexed _from, address indexed _to, uint256 _tokenId); + event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId); +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractScenario011.sol b/src/test/resources/soliditycode_v0.4.25/contractScenario011.sol new file mode 100644 index 00000000000..4d1e9c1ba12 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractScenario011.sol @@ -0,0 +1,2050 @@ +//pragma solidity ^0.4.11; + + +/** + * @title Ownable + * @dev The Ownable contract has an owner address, and provides basic authorization control + * functions, this simplifies the implementation of "user permissions". + */ +contract Ownable { + address public owner; + + + /** + * @dev The Ownable constructor sets the original `owner` of the contract to the sender + * account. + */ + constructor() public { + owner = msg.sender; + } + + + /** + * @dev Throws if called by any account other than the owner. + */ + modifier onlyOwner() { + require(msg.sender == owner); + _; + } + + + /** + * @dev Allows the current owner to transfer control of the contract to a newOwner. + * @param newOwner The address to transfer ownership to. + */ + function transferOwnership(address newOwner) public onlyOwner { + if (newOwner != address(0)) { + owner = newOwner; + } + } + +} + + + + +/// @title A facet of KittyCore that manages special access privileges. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. +contract KittyAccessControl { + // This facet controls access control for CryptoKitties. There are four roles managed here: + // + // - The CEO: The CEO can reassign other roles and change the addresses of our dependent smart + // contracts. It is also the only role that can unpause the smart contract. It is initially + // set to the address that created the smart contract in the KittyCore constructor. + // + // - The CFO: The CFO can withdraw funds from KittyCore and its auction contracts. + // + // - The COO: The COO can release gen0 kitties to auction, and mint promo cats. + // + // It should be noted that these roles are distinct without overlap in their access abilities, the + // abilities listed for each role above are exhaustive. In particular, while the CEO can assign any + // address to any role, the CEO address itself doesn't have the ability to act in those roles. This + // restriction is intentional so that we aren't tempted to use the CEO address frequently out of + // convenience. The less we use an address, the less likely it is that we somehow compromise the + // account. + + /// @dev Emited when contract is upgraded - See README.md for updgrade plan + event ContractUpgrade(address newContract); + + // The addresses of the accounts (or contracts) that can execute actions within each roles. + address public ceoAddress; + address public cfoAddress; + address public cooAddress; + + // @dev Keeps track whether the contract is paused. When that is true, most actions are blocked + bool public paused = false; + + /// @dev Access modifier for CEO-only functionality + modifier onlyCEO() { + require(msg.sender == ceoAddress); + _; + } + + /// @dev Access modifier for CFO-only functionality + modifier onlyCFO() { + require(msg.sender == cfoAddress); + _; + } + + /// @dev Access modifier for COO-only functionality + modifier onlyCOO() { + require(msg.sender == cooAddress); + _; + } + + modifier onlyCLevel() { + require( + msg.sender == cooAddress || + msg.sender == ceoAddress || + msg.sender == cfoAddress + ); + _; + } + + /// @dev Assigns a new address to act as the CEO. Only available to the current CEO. + /// @param _newCEO The address of the new CEO + function setCEO(address _newCEO) external onlyCEO { + require(_newCEO != address(0)); + + ceoAddress = _newCEO; + } + + /// @dev Assigns a new address to act as the CFO. Only available to the current CEO. + /// @param _newCFO The address of the new CFO + function setCFO(address _newCFO) external onlyCEO { + require(_newCFO != address(0)); + + cfoAddress = _newCFO; + } + + /// @dev Assigns a new address to act as the COO. Only available to the current CEO. + /// @param _newCOO The address of the new COO + function setCOO(address _newCOO) external onlyCEO { + require(_newCOO != address(0)); + + cooAddress = _newCOO; + } + + /*** Pausable functionality adapted from OpenZeppelin ***/ + + /// @dev Modifier to allow actions only when the contract IS NOT paused + modifier whenNotPaused() { + require(!paused); + _; + } + + /// @dev Modifier to allow actions only when the contract IS paused + modifier whenPaused { + require(paused); + _; + } + + /// @dev Called by any "C-level" role to pause the contract. Used only when + /// a bug or exploit is detected and we need to limit damage. + function pause() external onlyCLevel whenNotPaused { + paused = true; + } + + /// @dev Unpauses the smart contract. Can only be called by the CEO, since + /// one reason we may pause the contract is when CFO or COO accounts are + /// compromised. + /// @notice This is public rather than external so it can be called by + /// derived contracts. + function unpause() public onlyCEO whenPaused { + // can't unpause if contract was upgraded + paused = false; + } +} + + + + +/// @title Base contract for CryptoKitties. Holds all common structs, events and base variables. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. +contract KittyBase is KittyAccessControl { + /*** EVENTS ***/ + + /// @dev The Birth event is fired whenever a new kitten comes into existence. This obviously + /// includes any time a cat is created through the giveBirth method, but it is also called + /// when a new gen0 cat is created. + event Birth(address owner, uint256 kittyId, uint256 matronId, uint256 sireId, uint256 genes); + + /// @dev Transfer event as defined in current draft of ERC721. Emitted every time a kitten + /// ownership is assigned, including births. + event Transfer(address from, address to, uint256 tokenId); + + /*** DATA TYPES ***/ + + /// @dev The main Kitty struct. Every cat in CryptoKitties is represented by a copy + /// of this structure, so great care was taken to ensure that it fits neatly into + /// exactly two 256-bit words. Note that the order of the members in this structure + /// is important because of the byte-packing rules used by Ethereum. + /// Ref: http://solidity.readthedocs.io/en/develop/miscellaneous.html + struct Kitty { + // The Kitty's genetic code is packed into these 256-bits, the format is + // sooper-sekret! A cat's genes never change. + uint256 genes; + + // The timestamp from the block when this cat came into existence. + uint64 birthTime; + + // The minimum timestamp after which this cat can engage in breeding + // activities again. This same timestamp is used for the pregnancy + // timer (for matrons) as well as the siring cooldown. + uint64 cooldownEndBlock; + + // The ID of the parents of this kitty, set to 0 for gen0 cats. + // Note that using 32-bit unsigned integers limits us to a "mere" + // 4 billion cats. This number might seem small until you realize + // that Ethereum currently has a limit of about 500 million + // transactions per year! So, this definitely won't be a problem + // for several years (even as Ethereum learns to scale). + uint32 matronId; + uint32 sireId; + + // Set to the ID of the sire cat for matrons that are pregnant, + // zero otherwise. A non-zero value here is how we know a cat + // is pregnant. Used to retrieve the genetic material for the new + // kitten when the birth transpires. + uint32 siringWithId; + + // Set to the index in the cooldown array (see below) that represents + // the current cooldown duration for this Kitty. This starts at zero + // for gen0 cats, and is initialized to floor(generation/2) for others. + // Incremented by one for each successful breeding action, regardless + // of whether this cat is acting as matron or sire. + uint16 cooldownIndex; + + // The "generation number" of this cat. Cats minted by the CK contract + // for sale are called "gen0" and have a generation number of 0. The + // generation number of all other cats is the larger of the two generation + // numbers of their parents, plus one. + // (i.e. max(matron.generation, sire.generation) + 1) + uint16 generation; + } + + /*** CONSTANTS ***/ + + /// @dev A lookup table indicating the cooldown duration after any successful + /// breeding action, called "pregnancy time" for matrons and "siring cooldown" + /// for sires. Designed such that the cooldown roughly doubles each time a cat + /// is bred, encouraging owners not to just keep breeding the same cat over + /// and over again. Caps out at one week (a cat can breed an unbounded number + /// of times, and the maximum cooldown is always seven days). + uint32[14] public cooldowns = [ + uint32(1 minutes), + uint32(2 minutes), + uint32(5 minutes), + uint32(10 minutes), + uint32(30 minutes), + uint32(1 hours), + uint32(2 hours), + uint32(4 hours), + uint32(8 hours), + uint32(16 hours), + uint32(1 days), + uint32(2 days), + uint32(4 days), + uint32(7 days) + ]; + + // An approximation of currently how many seconds are in between blocks. + uint256 public secondsPerBlock = 15; + + /*** STORAGE ***/ + + /// @dev An array containing the Kitty struct for all Kitties in existence. The ID + /// of each cat is actually an index into this array. Note that ID 0 is a negacat, + /// the unKitty, the mythical beast that is the parent of all gen0 cats. A bizarre + /// creature that is both matron and sire... to itself! Has an invalid genetic code. + /// In other words, cat ID 0 is invalid... ;-) + Kitty[] kitties; + + /// @dev A mapping from cat IDs to the address that owns them. All cats have + /// some valid owner address, even gen0 cats are created with a non-zero owner. + mapping (uint256 => address) public kittyIndexToOwner; + + // @dev A mapping from owner address to count of tokens that address owns. + // Used internally inside balanceOf() to resolve ownership count. + mapping (address => uint256) ownershipTokenCount; + + /// @dev A mapping from KittyIDs to an address that has been approved to call + /// transferFrom(). Each Kitty can only have one approved address for transfer + /// at any time. A zero value means no approval is outstanding. + mapping (uint256 => address) public kittyIndexToApproved; + + /// @dev A mapping from KittyIDs to an address that has been approved to use + /// this Kitty for siring via breedWith(). Each Kitty can only have one approved + /// address for siring at any time. A zero value means no approval is outstanding. + mapping (uint256 => address) public sireAllowedToAddress; + + /// @dev The address of the ClockAuction contract that handles sales of Kitties. This + /// same contract handles both peer-to-peer sales as well as the gen0 sales which are + /// initiated every 15 minutes. + SaleClockAuction public saleAuction; + + /// @dev The address of a custom ClockAuction subclassed contract that handles siring + /// auctions. Needs to be separate from saleAuction because the actions taken on success + /// after a sales and siring auction are quite different. + SiringClockAuction public siringAuction; + + /// @dev Assigns ownership of a specific Kitty to an address. + function _transfer(address _from, address _to, uint256 _tokenId) internal { + // Since the number of kittens is capped to 2^32 we can't overflow this + ownershipTokenCount[_to]++; + // transfer ownership + kittyIndexToOwner[_tokenId] = _to; + // When creating new kittens _from is 0x0, but we can't account that address. + if (_from != address(0)) { + ownershipTokenCount[_from]--; + // once the kitten is transferred also clear sire allowances + delete sireAllowedToAddress[_tokenId]; + // clear any previously approved ownership exchange + delete kittyIndexToApproved[_tokenId]; + } + // Emit the transfer event. + emit Transfer(_from, _to, _tokenId); + } + + /// @dev An internal method that creates a new kitty and stores it. This + /// method doesn't do any checking and should only be called when the + /// input data is known to be valid. Will generate both a Birth event + /// and a Transfer event. + /// @param _matronId The kitty ID of the matron of this cat (zero for gen0) + /// @param _sireId The kitty ID of the sire of this cat (zero for gen0) + /// @param _generation The generation number of this cat, must be computed by caller. + /// @param _genes The kitty's genetic code. + /// @param _owner The inital owner of this cat, must be non-zero (except for the unKitty, ID 0) + function _createKitty( + uint256 _matronId, + uint256 _sireId, + uint256 _generation, + uint256 _genes, + address _owner + ) + internal + returns (uint) + { + // These requires are not strictly necessary, our calling code should make + // sure that these conditions are never broken. However! _createKitty() is already + // an expensive call (for storage), and it doesn't hurt to be especially careful + // to ensure our data structures are always valid. + require(_matronId == uint256(uint32(_matronId))); + require(_sireId == uint256(uint32(_sireId))); + require(_generation == uint256(uint16(_generation))); + + // New kitty starts with the same cooldown as parent gen/2 + uint16 cooldownIndex = uint16(_generation / 2); + if (cooldownIndex > 13) { + cooldownIndex = 13; + } + + Kitty memory _kitty = Kitty({ + genes: _genes, + birthTime: uint64(now), + cooldownEndBlock: 0, + matronId: uint32(_matronId), + sireId: uint32(_sireId), + siringWithId: 0, + cooldownIndex: cooldownIndex, + generation: uint16(_generation) + }); + uint256 newKittenId = kitties.push(_kitty) - 1; + + // It's probably never going to happen, 4 billion cats is A LOT, but + // let's just be 100% sure we never let this happen. + require(newKittenId == uint256(uint32(newKittenId))); + + // emit the birth event + emit Birth( + _owner, + newKittenId, + uint256(_kitty.matronId), + uint256(_kitty.sireId), + _kitty.genes + ); + + // This will assign ownership, and also emit the Transfer event as + // per ERC721 draft + _transfer(address(0), _owner, newKittenId); + + return newKittenId; + } + + // Any C-level can fix how many seconds per blocks are currently observed. + function setSecondsPerBlock(uint256 secs) external onlyCLevel { + require(secs < cooldowns[0]); + secondsPerBlock = secs; + } +} + + +/// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens +/// @author Dieter Shirley (https://github.com/dete) +contract ERC721 { + // Required methods + function totalSupply() public view returns (uint256 total); + function balanceOf(address _owner) public view returns (uint256 balance); + function ownerOf(uint256 _tokenId) external view returns (address owner); + function approve(address _to, uint256 _tokenId) external; + function transfer(address _to, uint256 _tokenId) external; + function transferFrom(address _from, address _to, uint256 _tokenId) external; + + // Events + event Transfer(address from, address to, uint256 tokenId); + event Approval(address owner, address approved, uint256 tokenId); + + // Optional + // function name() public view returns (string name); + // function symbol() public view returns (string symbol); + // function tokensOfOwner(address _owner) external view returns (uint256[] tokenIds); + // function tokenMetadata(uint256 _tokenId, string _preferredTransport) public view returns (string infoUrl); + + // ERC-165 Compatibility (https://github.com/ethereum/EIPs/issues/165) + function supportsInterface(bytes4 _interfaceID) external view returns (bool); +} + + +/// @title The facet of the CryptoKitties core contract that manages ownership, ERC-721 (draft) compliant. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev Ref: https://github.com/ethereum/EIPs/issues/721 +/// See the KittyCore contract documentation to understand how the various contract facets are arranged. +contract KittyOwnership is ERC721, KittyBase { + + /// @notice Name and symbol of the non fungible token, as defined in ERC721. + string public constant name = "CryptoKitties"; + string public constant symbol = "CK"; + + // The contract that will return kitty metadata + ERC721Metadata public erc721Metadata; + + bytes4 constant InterfaceSignature_ERC165 = + bytes4(keccak256('supportsInterface(bytes4)')); + + bytes4 constant InterfaceSignature_ERC721 = + bytes4(keccak256('name()')) ^ + bytes4(keccak256('symbol()')) ^ + bytes4(keccak256('totalSupply()')) ^ + bytes4(keccak256('balanceOf(address)')) ^ + bytes4(keccak256('ownerOf(uint256)')) ^ + bytes4(keccak256('approve(address,uint256)')) ^ + bytes4(keccak256('transfer(address,uint256)')) ^ + bytes4(keccak256('transferFrom(address,address,uint256)')) ^ + bytes4(keccak256('tokensOfOwner(address)')) ^ + bytes4(keccak256('tokenMetadata(uint256,string)')); + + /// @notice Introspection interface as per ERC-165 (https://github.com/ethereum/EIPs/issues/165). + /// Returns true for any standardized interfaces implemented by this contract. We implement + /// ERC-165 (obviously!) and ERC-721. + function supportsInterface(bytes4 _interfaceID) external view returns (bool) + { + // DEBUG ONLY + //require((InterfaceSignature_ERC165 == 0x01ffc9a7) && (InterfaceSignature_ERC721 == 0x9a20483d)); + + return ((_interfaceID == InterfaceSignature_ERC165) || (_interfaceID == InterfaceSignature_ERC721)); + } + + /// @dev Set the address of the sibling contract that tracks metadata. + /// CEO only. + function setMetadataAddress(address _contractAddress) public onlyCEO { + erc721Metadata = ERC721Metadata(_contractAddress); + } + + // Internal utility functions: These functions all assume that their input arguments + // are valid. We leave it to public methods to sanitize their inputs and follow + // the required logic. + + /// @dev Checks if a given address is the current owner of a particular Kitty. + /// @param _claimant the address we are validating against. + /// @param _tokenId kitten id, only valid when > 0 + function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { + return kittyIndexToOwner[_tokenId] == _claimant; + } + + /// @dev Checks if a given address currently has transferApproval for a particular Kitty. + /// @param _claimant the address we are confirming kitten is approved for. + /// @param _tokenId kitten id, only valid when > 0 + function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) { + return kittyIndexToApproved[_tokenId] == _claimant; + } + + /// @dev Marks an address as being approved for transferFrom(), overwriting any previous + /// approval. Setting _approved to address(0) clears all transfer approval. + /// NOTE: _approve() does NOT send the Approval event. This is intentional because + /// _approve() and transferFrom() are used together for putting Kitties on auction, and + /// there is no value in spamming the log with Approval events in that case. + function _approve(uint256 _tokenId, address _approved) internal { + kittyIndexToApproved[_tokenId] = _approved; + } + + /// @notice Returns the number of Kitties owned by a specific address. + /// @param _owner The owner address to check. + /// @dev Required for ERC-721 compliance + function balanceOf(address _owner) public view returns (uint256 count) { + return ownershipTokenCount[_owner]; + } + + /// @notice Transfers a Kitty to another address. If transferring to a smart + /// contract be VERY CAREFUL to ensure that it is aware of ERC-721 (or + /// CryptoKitties specifically) or your Kitty may be lost forever. Seriously. + /// @param _to The address of the recipient, can be a user or contract. + /// @param _tokenId The ID of the Kitty to transfer. + /// @dev Required for ERC-721 compliance. + function transfer( + address _to, + uint256 _tokenId + ) + external + whenNotPaused + { + // Safety check to prevent against an unexpected 0x0 default. + require(_to != address(0)); + // Disallow transfers to this contract to prevent accidental misuse. + // The contract should never own any kitties (except very briefly + // after a gen0 cat is created and before it goes on auction). + require(_to != address(this)); + // Disallow transfers to the auction contracts to prevent accidental + // misuse. Auction contracts should only take ownership of kitties + // through the allow + transferFrom flow. + require(_to != address(saleAuction)); + require(_to != address(siringAuction)); + + // You can only send your own cat. + require(_owns(msg.sender, _tokenId)); + + // Reassign ownership, clear pending approvals, emit Transfer event. + _transfer(msg.sender, _to, _tokenId); + } + + /// @notice Grant another address the right to transfer a specific Kitty via + /// transferFrom(). This is the preferred flow for transfering NFTs to contracts. + /// @param _to The address to be granted transfer approval. Pass address(0) to + /// clear all approvals. + /// @param _tokenId The ID of the Kitty that can be transferred if this call succeeds. + /// @dev Required for ERC-721 compliance. + function approve( + address _to, + uint256 _tokenId + ) + external + whenNotPaused + { + // Only an owner can grant transfer approval. + require(_owns(msg.sender, _tokenId)); + + // Register the approval (replacing any previous approval). + _approve(_tokenId, _to); + + // Emit approval event. + emit Approval(msg.sender, _to, _tokenId); + } + + /// @notice Transfer a Kitty owned by another address, for which the calling address + /// has previously been granted transfer approval by the owner. + /// @param _from The address that owns the Kitty to be transfered. + /// @param _to The address that should take ownership of the Kitty. Can be any address, + /// including the caller. + /// @param _tokenId The ID of the Kitty to be transferred. + /// @dev Required for ERC-721 compliance. + function transferFrom( + address _from, + address _to, + uint256 _tokenId + ) + external + whenNotPaused + { + // Safety check to prevent against an unexpected 0x0 default. + require(_to != address(0)); + // Disallow transfers to this contract to prevent accidental misuse. + // The contract should never own any kitties (except very briefly + // after a gen0 cat is created and before it goes on auction). + require(_to != address(this)); + // Check for approval and valid ownership + require(_approvedFor(msg.sender, _tokenId)); + require(_owns(_from, _tokenId)); + + // Reassign ownership (also clears pending approvals and emits Transfer event). + _transfer(_from, _to, _tokenId); + } + + /// @notice Returns the total number of Kitties currently in existence. + /// @dev Required for ERC-721 compliance. + function totalSupply() public view returns (uint) { + return kitties.length - 1; + } + + /// @notice Returns the address currently assigned ownership of a given Kitty. + /// @dev Required for ERC-721 compliance. + function ownerOf(uint256 _tokenId) + external + view + returns (address owner) + { + owner = kittyIndexToOwner[_tokenId]; + + require(owner != address(0)); + } + + /// @notice Returns a list of all Kitty IDs assigned to an address. + /// @param _owner The owner whose Kitties we are interested in. + /// @dev This method MUST NEVER be called by smart contract code. First, it's fairly + /// expensive (it walks the entire Kitty array looking for cats belonging to owner), + /// but it also returns a dynamic array, which is only supported for web3 calls, and + /// not contract-to-contract calls. + function tokensOfOwner(address _owner) external view returns(uint256[] memory ownerTokens) { + uint256 tokenCount = balanceOf(_owner); + + if (tokenCount == 0) { + // Return an empty array + return new uint256[](0); + } else { + uint256[] memory result = new uint256[](tokenCount); + uint256 totalCats = totalSupply(); + uint256 resultIndex = 0; + + // We count on the fact that all cats have IDs starting at 1 and increasing + // sequentially up to the totalCat count. + uint256 catId; + + for (catId = 1; catId <= totalCats; catId++) { + if (kittyIndexToOwner[catId] == _owner) { + result[resultIndex] = catId; + resultIndex++; + } + } + + return result; + } + } + + /// @dev Adapted from memcpy() by @arachnid (Nick Johnson ) + /// This method is licenced under the Apache License. + /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol + function _memcpy(uint _dest, uint _src, uint _len) private view { + // Copy word-length chunks while possible + for(; _len >= 32; _len -= 32) { + assembly { + mstore(_dest, mload(_src)) + } + _dest += 32; + _src += 32; + } + + // Copy remaining bytes + uint256 mask = 256 ** (32 - _len) - 1; + assembly { + let srcpart := and(mload(_src), not(mask)) + let destpart := and(mload(_dest), mask) + mstore(_dest, or(destpart, srcpart)) + } + } + + /// @dev Adapted from toString(slice) by @arachnid (Nick Johnson ) + /// This method is licenced under the Apache License. + /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol + function _toString(bytes32[4] memory _rawBytes, uint256 _stringLength) private view returns (string memory) { + string memory outputString = new string(_stringLength); + uint256 outputPtr; + uint256 bytesPtr; + + assembly { + outputPtr := add(outputString, 32) + bytesPtr := _rawBytes + } + + _memcpy(outputPtr, bytesPtr, _stringLength); + + return outputString; + } + + /// @notice Returns a URI pointing to a metadata package for this token conforming to + /// ERC-721 (https://github.com/ethereum/EIPs/issues/721) + /// @param _tokenId The ID number of the Kitty whose metadata should be returned. + function tokenMetadata(uint256 _tokenId, string _preferredTransport) external view returns (string infoUrl) { + require( address(erc721Metadata) != address(0)); + bytes32[4] memory buffer; + uint256 count; + (buffer, count) = erc721Metadata.getMetadata(_tokenId, _preferredTransport); + + return _toString(buffer, count); + } +} + + + + +/// @title A facet of KittyCore that manages Kitty siring, gestation, and birth. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. +contract KittyBreeding is KittyOwnership { + + /// @dev The Pregnant event is fired when two cats successfully breed and the pregnancy + /// timer begins for the matron. + event Pregnant(address owner, uint256 matronId, uint256 sireId, uint256 cooldownEndBlock); + + /// @notice The minimum payment required to use breedWithAuto(). This fee goes towards + /// the gas cost paid by whatever calls giveBirth(), and can be dynamically updated by + /// the COO role as the gas price changes. + uint256 public autoBirthFee = 2 sun; + + // Keeps track of number of pregnant kitties. + uint256 public pregnantKitties; + + /// @dev The address of the sibling contract that is used to implement the sooper-sekret + /// genetic combination algorithm. + GeneScienceInterface public geneScience; + + /// @dev Update the address of the genetic contract, can only be called by the CEO. + /// @param _address An address of a GeneScience contract instance to be used from this point forward. + function setGeneScienceAddress(address _address) external onlyCEO { + GeneScienceInterface candidateContract = GeneScienceInterface(_address); + + // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 + require(candidateContract.isGeneScience()); + + // Set the new contract address + geneScience = candidateContract; + } + + /// @dev Checks that a given kitten is able to breed. Requires that the + /// current cooldown is finished (for sires) and also checks that there is + /// no pending pregnancy. + function _isReadyToBreed(Kitty memory _kit) internal view returns (bool) { + // In addition to checking the cooldownEndBlock, we also need to check to see if + // the cat has a pending birth; there can be some period of time between the end + // of the pregnacy timer and the birth event. + return (_kit.siringWithId == 0) && (_kit.cooldownEndBlock <= uint64(block.number)); + } + + /// @dev Check if a sire has authorized breeding with this matron. True if both sire + /// and matron have the same owner, or if the sire has given siring permission to + /// the matron's owner (via approveSiring()). + function _isSiringPermitted(uint256 _sireId, uint256 _matronId) internal view returns (bool) { + address matronOwner = kittyIndexToOwner[_matronId]; + address sireOwner = kittyIndexToOwner[_sireId]; + + // Siring is okay if they have same owner, or if the matron's owner was given + // permission to breed with this sire. + return (matronOwner == sireOwner || sireAllowedToAddress[_sireId] == matronOwner); + } + + /// @dev Set the cooldownEndTime for the given Kitty, based on its current cooldownIndex. + /// Also increments the cooldownIndex (unless it has hit the cap). + /// @param _kitten A reference to the Kitty in storage which needs its timer started. + function _triggerCooldown(Kitty storage _kitten) internal { + // Compute an estimation of the cooldown time in blocks (based on current cooldownIndex). + _kitten.cooldownEndBlock = uint64((cooldowns[_kitten.cooldownIndex]/secondsPerBlock) + block.number); + + // Increment the breeding count, clamping it at 13, which is the length of the + // cooldowns array. We could check the array size dynamically, but hard-coding + // this as a constant saves gas. Yay, Solidity! + if (_kitten.cooldownIndex < 13) { + _kitten.cooldownIndex += 1; + } + } + + /// @notice Grants approval to another user to sire with one of your Kitties. + /// @param _addr The address that will be able to sire with your Kitty. Set to + /// address(0) to clear all siring approvals for this Kitty. + /// @param _sireId A Kitty that you own that _addr will now be able to sire with. + function approveSiring(address _addr, uint256 _sireId) + external + whenNotPaused + { + require(_owns(msg.sender, _sireId)); + sireAllowedToAddress[_sireId] = _addr; + } + + /// @dev Updates the minimum payment required for calling giveBirthAuto(). Can only + /// be called by the COO address. (This fee is used to offset the gas cost incurred + /// by the autobirth daemon). + function setAutoBirthFee(uint256 val) external onlyCOO { + autoBirthFee = val; + } + + /// @dev Checks to see if a given Kitty is pregnant and (if so) if the gestation + /// period has passed. + function _isReadyToGiveBirth(Kitty memory _matron) private view returns (bool) { + return (_matron.siringWithId != 0) && (_matron.cooldownEndBlock <= uint64(block.number)); + } + + /// @notice Checks that a given kitten is able to breed (i.e. it is not pregnant or + /// in the middle of a siring cooldown). + /// @param _kittyId reference the id of the kitten, any user can inquire about it + function isReadyToBreed(uint256 _kittyId) + public + view + returns (bool) + { + require(_kittyId > 0); + Kitty storage kit = kitties[_kittyId]; + return _isReadyToBreed(kit); + } + + /// @dev Checks whether a kitty is currently pregnant. + /// @param _kittyId reference the id of the kitten, any user can inquire about it + function isPregnant(uint256 _kittyId) + public + view + returns (bool) + { + require(_kittyId > 0); + // A kitty is pregnant if and only if this field is set + return kitties[_kittyId].siringWithId != 0; + } + + /// @dev Internal check to see if a given sire and matron are a valid mating pair. DOES NOT + /// check ownership permissions (that is up to the caller). + /// @param _matron A reference to the Kitty struct of the potential matron. + /// @param _matronId The matron's ID. + /// @param _sire A reference to the Kitty struct of the potential sire. + /// @param _sireId The sire's ID + function _isValidMatingPair( + Kitty storage _matron, + uint256 _matronId, + Kitty storage _sire, + uint256 _sireId + ) + private + view + returns(bool) + { + // A Kitty can't breed with itself! + if (_matronId == _sireId) { + return false; + } + + // Kitties can't breed with their parents. + if (_matron.matronId == _sireId || _matron.sireId == _sireId) { + return false; + } + if (_sire.matronId == _matronId || _sire.sireId == _matronId) { + return false; + } + + // We can short circuit the sibling check (below) if either cat is + // gen zero (has a matron ID of zero). + if (_sire.matronId == 0 || _matron.matronId == 0) { + return true; + } + + // Kitties can't breed with full or half siblings. + if (_sire.matronId == _matron.matronId || _sire.matronId == _matron.sireId) { + return false; + } + if (_sire.sireId == _matron.matronId || _sire.sireId == _matron.sireId) { + return false; + } + + // Everything seems cool! Let's get DTF. + return true; + } + + /// @dev Internal check to see if a given sire and matron are a valid mating pair for + /// breeding via auction (i.e. skips ownership and siring approval checks). + function _canBreedWithViaAuction(uint256 _matronId, uint256 _sireId) + internal + view + returns (bool) + { + Kitty storage matron = kitties[_matronId]; + Kitty storage sire = kitties[_sireId]; + return _isValidMatingPair(matron, _matronId, sire, _sireId); + } + + /// @notice Checks to see if two cats can breed together, including checks for + /// ownership and siring approvals. Does NOT check that both cats are ready for + /// breeding (i.e. breedWith could still fail until the cooldowns are finished). + /// TODO: Shouldn't this check pregnancy and cooldowns?!? + /// @param _matronId The ID of the proposed matron. + /// @param _sireId The ID of the proposed sire. + function canBreedWith(uint256 _matronId, uint256 _sireId) + external + view + returns(bool) + { + require(_matronId > 0); + require(_sireId > 0); + Kitty storage matron = kitties[_matronId]; + Kitty storage sire = kitties[_sireId]; + return _isValidMatingPair(matron, _matronId, sire, _sireId) && + _isSiringPermitted(_sireId, _matronId); + } + + /// @dev Internal utility function to initiate breeding, assumes that all breeding + /// requirements have been checked. + function _breedWith(uint256 _matronId, uint256 _sireId) internal { + // Grab a reference to the Kitties from storage. + Kitty storage sire = kitties[_sireId]; + Kitty storage matron = kitties[_matronId]; + + // Mark the matron as pregnant, keeping track of who the sire is. + matron.siringWithId = uint32(_sireId); + + // Trigger the cooldown for both parents. + _triggerCooldown(sire); + _triggerCooldown(matron); + + // Clear siring permission for both parents. This may not be strictly necessary + // but it's likely to avoid confusion! + delete sireAllowedToAddress[_matronId]; + delete sireAllowedToAddress[_sireId]; + + // Every time a kitty gets pregnant, counter is incremented. + pregnantKitties++; + + // Emit the pregnancy event. + emit Pregnant(kittyIndexToOwner[_matronId], _matronId, _sireId, matron.cooldownEndBlock); + } + + /// @notice Breed a Kitty you own (as matron) with a sire that you own, or for which you + /// have previously been given Siring approval. Will either make your cat pregnant, or will + /// fail entirely. Requires a pre-payment of the fee given out to the first caller of giveBirth() + /// @param _matronId The ID of the Kitty acting as matron (will end up pregnant if successful) + /// @param _sireId The ID of the Kitty acting as sire (will begin its siring cooldown if successful) + function breedWithAuto(uint256 _matronId, uint256 _sireId) + external + payable + whenNotPaused + { + // Checks for payment. + require(msg.value >= autoBirthFee); + + // Caller must own the matron. + require(_owns(msg.sender, _matronId)); + + // Neither sire nor matron are allowed to be on auction during a normal + // breeding operation, but we don't need to check that explicitly. + // For matron: The caller of this function can't be the owner of the matron + // because the owner of a Kitty on auction is the auction house, and the + // auction house will never call breedWith(). + // For sire: Similarly, a sire on auction will be owned by the auction house + // and the act of transferring ownership will have cleared any oustanding + // siring approval. + // Thus we don't need to spend gas explicitly checking to see if either cat + // is on auction. + + // Check that matron and sire are both owned by caller, or that the sire + // has given siring permission to caller (i.e. matron's owner). + // Will fail for _sireId = 0 + require(_isSiringPermitted(_sireId, _matronId)); + + // Grab a reference to the potential matron + Kitty storage matron = kitties[_matronId]; + + // Make sure matron isn't pregnant, or in the middle of a siring cooldown + require(_isReadyToBreed(matron)); + + // Grab a reference to the potential sire + Kitty storage sire = kitties[_sireId]; + + // Make sure sire isn't pregnant, or in the middle of a siring cooldown + require(_isReadyToBreed(sire)); + + // Test that these cats are a valid mating pair. + require(_isValidMatingPair( + matron, + _matronId, + sire, + _sireId + )); + + // All checks passed, kitty gets pregnant! + _breedWith(_matronId, _sireId); + } + + /// @notice Have a pregnant Kitty give birth! + /// @param _matronId A Kitty ready to give birth. + /// @return The Kitty ID of the new kitten. + /// @dev Looks at a given Kitty and, if pregnant and if the gestation period has passed, + /// combines the genes of the two parents to create a new kitten. The new Kitty is assigned + /// to the current owner of the matron. Upon successful completion, both the matron and the + /// new kitten will be ready to breed again. Note that anyone can call this function (if they + /// are willing to pay the gas!), but the new kitten always goes to the mother's owner. + function giveBirth(uint256 _matronId) + external + whenNotPaused + returns(uint256) + { + // Grab a reference to the matron in storage. + Kitty storage matron = kitties[_matronId]; + + // Check that the matron is a valid cat. + require(matron.birthTime != 0); + + // Check that the matron is pregnant, and that its time has come! + require(_isReadyToGiveBirth(matron)); + + // Grab a reference to the sire in storage. + uint256 sireId = matron.siringWithId; + Kitty storage sire = kitties[sireId]; + + // Determine the higher generation number of the two parents + uint16 parentGen = matron.generation; + if (sire.generation > matron.generation) { + parentGen = sire.generation; + } + + // Call the sooper-sekret gene mixing operation. + uint256 childGenes = geneScience.mixGenes(matron.genes, sire.genes, matron.cooldownEndBlock - 1); + + // Make the new kitten! + address owner = kittyIndexToOwner[_matronId]; + uint256 kittenId = _createKitty(_matronId, matron.siringWithId, parentGen + 1, childGenes, owner); + + // Clear the reference to sire from the matron (REQUIRED! Having siringWithId + // set is what marks a matron as being pregnant.) + delete matron.siringWithId; + + // Every time a kitty gives birth counter is decremented. + pregnantKitties--; + + // Send the balance fee to the person who made birth happen. + msg.sender.transfer(autoBirthFee); + + // return the new kitten's ID + return kittenId; + } +} + + + +/// @title Handles creating auctions for sale and siring of kitties. +/// This wrapper of ReverseAuction exists only so that users can create +/// auctions with only one transaction. +contract KittyAuction is KittyBreeding { + + // @notice The auction contract variables are defined in KittyBase to allow + // us to refer to them in KittyOwnership to prevent accidental transfers. + // `saleAuction` refers to the auction for gen0 and p2p sale of kitties. + // `siringAuction` refers to the auction for siring rights of kitties. + + /// @dev Sets the reference to the sale auction. + /// @param _address - Address of sale contract. + function setSaleAuctionAddress(address _address) external onlyCEO { + SaleClockAuction candidateContract = SaleClockAuction(_address); + + // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 + require(candidateContract.isSaleClockAuction()); + + // Set the new contract address + saleAuction = candidateContract; + } + + /// @dev Sets the reference to the siring auction. + /// @param _address - Address of siring contract. + function setSiringAuctionAddress(address _address) external onlyCEO { + SiringClockAuction candidateContract = SiringClockAuction(_address); + + // NOTE: verify that a contract is what we expect - https://github.com/Lunyr/crowdsale-contracts/blob/cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 + require(candidateContract.isSiringClockAuction()); + + // Set the new contract address + siringAuction = candidateContract; + } + + /// @dev Put a kitty up for auction. + /// Does some ownership trickery to create auctions in one tx. + function createSaleAuction( + uint256 _kittyId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration + ) + external + whenNotPaused + { + // Auction contract checks input sizes + // If kitty is already on any auction, this will throw + // because it will be owned by the auction contract. + require(_owns(msg.sender, _kittyId)); + // Ensure the kitty is not pregnant to prevent the auction + // contract accidentally receiving ownership of the child. + // NOTE: the kitty IS allowed to be in a cooldown. + require(!isPregnant(_kittyId)); + _approve(_kittyId, address(saleAuction)); + // Sale auction throws if inputs are invalid and clears + // transfer and sire approval after escrowing the kitty. + saleAuction.createAuction( + _kittyId, + _startingPrice, + _endingPrice, + _duration, + msg.sender + ); + } + + /// @dev Put a kitty up for auction to be sire. + /// Performs checks to ensure the kitty can be sired, then + /// delegates to reverse auction. + function createSiringAuction( + uint256 _kittyId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration + ) + external + whenNotPaused + { + // Auction contract checks input sizes + // If kitty is already on any auction, this will throw + // because it will be owned by the auction contract. + require(_owns(msg.sender, _kittyId)); + require(isReadyToBreed(_kittyId)); + _approve(_kittyId, address(siringAuction)); + // Siring auction throws if inputs are invalid and clears + // transfer and sire approval after escrowing the kitty. + siringAuction.createAuction( + _kittyId, + _startingPrice, + _endingPrice, + _duration, + msg.sender + ); + } + + /// @dev Completes a siring auction by bidding. + /// Immediately breeds the winning matron with the sire on auction. + /// @param _sireId - ID of the sire on auction. + /// @param _matronId - ID of the matron owned by the bidder. + function bidOnSiringAuction( + uint256 _sireId, + uint256 _matronId + ) + external + payable + whenNotPaused + { + // Auction contract checks input sizes + require(_owns(msg.sender, _matronId)); + require(isReadyToBreed(_matronId)); + require(_canBreedWithViaAuction(_matronId, _sireId)); + + // Define the current price of the auction. + uint256 currentPrice = siringAuction.getCurrentPrice(_sireId); + require(msg.value >= currentPrice + autoBirthFee); + + // Siring auction will throw if the bid fails. + siringAuction.bid.value(msg.value - autoBirthFee)(_sireId); + _breedWith(uint32(_matronId), uint32(_sireId)); + } + + /// @dev Transfers the balance of the sale auction contract + /// to the KittyCore contract. We use two-step withdrawal to + /// prevent two transfer calls in the auction bid function. + function withdrawAuctionBalances() external onlyCLevel { + saleAuction.withdrawBalance(); + siringAuction.withdrawBalance(); + } +} + + +/// @title all functions related to creating kittens +contract KittyMinting is KittyAuction { + + // Limits the number of cats the contract owner can ever create. + uint256 public constant PROMO_CREATION_LIMIT = 5000; + uint256 public constant GEN0_CREATION_LIMIT = 45000; + + // Constants for gen0 auctions. + uint256 public constant GEN0_STARTING_PRICE = 10 sun; + uint256 public constant GEN0_AUCTION_DURATION = 1 days; + + // Counts the number of cats the contract owner has created. + uint256 public promoCreatedCount; + uint256 public gen0CreatedCount; + + /// @dev we can create promo kittens, up to a limit. Only callable by COO + /// @param _genes the encoded genes of the kitten to be created, any value is accepted + /// @param _owner the future owner of the created kittens. Default to contract COO + function createPromoKitty(uint256 _genes, address _owner) external onlyCOO { + address kittyOwner = _owner; + if (kittyOwner == address(0)) { + kittyOwner = cooAddress; + } + require(promoCreatedCount < PROMO_CREATION_LIMIT); + + promoCreatedCount++; + _createKitty(0, 0, 0, _genes, kittyOwner); + } + + /// @dev Creates a new gen0 kitty with the given genes and + /// creates an auction for it. + function createGen0Auction(uint256 _genes) external onlyCOO { + require(gen0CreatedCount < GEN0_CREATION_LIMIT); + + uint256 kittyId = _createKitty(0, 0, 0, _genes, address(this)); + _approve(kittyId, address(saleAuction)); + + saleAuction.createAuction( + kittyId, + _computeNextGen0Price(), + 0, + GEN0_AUCTION_DURATION, + address(uint160(address(this))) + ); + + gen0CreatedCount++; + } + + /// @dev Computes the next gen0 auction starting price, given + /// the average of the past 5 prices + 50%. + function _computeNextGen0Price() internal view returns (uint256) { + uint256 avePrice = saleAuction.averageGen0SalePrice(); + + // Sanity check to ensure we don't overflow arithmetic + require(avePrice == uint256(uint128(avePrice))); + + uint256 nextPrice = avePrice + (avePrice / 2); + + // We never auction for less than starting price + if (nextPrice < GEN0_STARTING_PRICE) { + nextPrice = GEN0_STARTING_PRICE; + } + + return nextPrice; + } +} + + + +/// @title CryptoKitties: Collectible, breedable, and oh-so-adorable cats on the Ethereum blockchain. +/// @author Axiom Zen (https://www.axiomzen.co) +/// @dev The main CryptoKitties contract, keeps track of kittens so they don't wander around and get lost. +contract KittyCore is KittyMinting { + + // This is the main CryptoKitties contract. In order to keep our code seperated into logical sections, + // we've broken it up in two ways. First, we have several seperately-instantiated sibling contracts + // that handle auctions and our super-top-secret genetic combination algorithm. The auctions are + // seperate since their logic is somewhat complex and there's always a risk of subtle bugs. By keeping + // them in their own contracts, we can upgrade them without disrupting the main contract that tracks + // kitty ownership. The genetic combination algorithm is kept seperate so we can open-source all of + // the rest of our code without making it _too_ easy for folks to figure out how the genetics work. + // Don't worry, I'm sure someone will reverse engineer it soon enough! + // + // Secondly, we break the core contract into multiple files using inheritence, one for each major + // facet of functionality of CK. This allows us to keep related code bundled together while still + // avoiding a single giant file with everything in it. The breakdown is as follows: + // + // - KittyBase: This is where we define the most fundamental code shared throughout the core + // functionality. This includes our main data storage, constants and data types, plus + // internal functions for managing these items. + // + // - KittyAccessControl: This contract manages the various addresses and constraints for operations + // that can be executed only by specific roles. Namely CEO, CFO and COO. + // + // - KittyOwnership: This provides the methods required for basic non-fungible token + // transactions, following the draft ERC-721 spec (https://github.com/ethereum/EIPs/issues/721). + // + // - KittyBreeding: This file contains the methods necessary to breed cats together, including + // keeping track of siring offers, and relies on an external genetic combination contract. + // + // - KittyAuctions: Here we have the public methods for auctioning or bidding on cats or siring + // services. The actual auction functionality is handled in two sibling contracts (one + // for sales and one for siring), while auction creation and bidding is mostly mediated + // through this facet of the core contract. + // + // - KittyMinting: This final facet contains the functionality we use for creating new gen0 cats. + // We can make up to 5000 "promo" cats that can be given away (especially important when + // the community is new), and all others can only be created and then immediately put up + // for auction via an algorithmically determined starting price. Regardless of how they + // are created, there is a hard limit of 50k gen0 cats. After that, it's all up to the + // community to breed, breed, breed! + + // Set in case the core contract is broken and an upgrade is required + address public newContractAddress; + + /// @notice Creates the main CryptoKitties smart contract instance. + constructor() public { + // Starts paused. + paused = true; + + // the creator of the contract is the initial CEO + ceoAddress = msg.sender; + + // the creator of the contract is also the initial COO + cooAddress = msg.sender; + + // start with the mythical kitten 0 - so we don't have generation-0 parent issues + _createKitty(0, 0, 0, uint256(-1), address(0)); + } + + /// @dev Used to mark the smart contract as upgraded, in case there is a serious + /// breaking bug. This method does nothing but keep track of the new contract and + /// emit a message indicating that the new address is set. It's up to clients of this + /// contract to update to the new contract address in that case. (This contract will + /// be paused indefinitely if such an upgrade takes place.) + /// @param _v2Address new address + function setNewAddress(address _v2Address) external onlyCEO whenPaused { + // See README.md for updgrade plan + newContractAddress = _v2Address; + emit ContractUpgrade(_v2Address); + } + + /// @notice No tipping! + /// @dev Reject all Ether from being sent here, unless it's from one of the + /// two auction contracts. (Hopefully, we can prevent user accidents.) + function() external payable { + require( + msg.sender == address(saleAuction) || + msg.sender == address(siringAuction) + ); + } + + /// @notice Returns all the relevant information about a specific kitty. + /// @param _id The ID of the kitty of interest. + function getKitty(uint256 _id) + external + view + returns ( + bool isGestating, + bool isReady, + uint256 cooldownIndex, + uint256 nextActionAt, + uint256 siringWithId, + uint256 birthTime, + uint256 matronId, + uint256 sireId, + uint256 generation, + uint256 genes + ) { + Kitty storage kit = kitties[_id]; + + // if this variable is 0 then it's not gestating + isGestating = (kit.siringWithId != 0); + isReady = (kit.cooldownEndBlock <= block.number); + cooldownIndex = uint256(kit.cooldownIndex); + nextActionAt = uint256(kit.cooldownEndBlock); + siringWithId = uint256(kit.siringWithId); + birthTime = uint256(kit.birthTime); + matronId = uint256(kit.matronId); + sireId = uint256(kit.sireId); + generation = uint256(kit.generation); + genes = kit.genes; + } + + /// @dev Override unpause so it requires all external contract addresses + /// to be set before contract can be unpaused. Also, we can't have + /// newContractAddress set either, because then the contract was upgraded. + /// @notice This is public rather than external so we can call super.unpause + /// without using an expensive CALL. + + function unpause() public onlyCEO whenPaused { + require(address(saleAuction) != address(0)); + require(address(siringAuction) != address(0)); + require(address(geneScience) != address(0)); + require(newContractAddress == address(0)); + + // Actually unpause the contract. + super.unpause(); + } + + // @dev Allows the CFO to capture the balance available to the contract. + function withdrawBalance() external onlyCFO { + uint256 balance = address(this).balance; + // Subtract all the currently pregnant kittens we have, plus 1 of margin. + uint256 subtractFees = (pregnantKitties + 1) * autoBirthFee; + + if (balance > subtractFees) { + cfoAddress.transfer(balance - subtractFees); + } + } +} + + + + + + + + + + + + + +// // Auction wrapper functions + + +// Auction wrapper functions + + + + + + + +/// @title SEKRETOOOO +contract GeneScienceInterface { + + function isGeneScience() public pure returns (bool){ + return true; + } + + /// @dev given genes of kitten 1 & 2, return a genetic combination - may have a random factor + /// @param genes1 genes of mom + /// @param genes2 genes of sire + /// @return the genes that are supposed to be passed down the child + function mixGenes(uint256 genes1, uint256 genes2, uint256 targetBlock) public pure returns (uint256){ + + return (genes1+genes2+targetBlock)/2; + + +} +} + + + + + + + + + + + + + + + + +/// @title The external contract that is responsible for generating metadata for the kitties, +/// it has one function that will return the data as bytes. +contract ERC721Metadata { + /// @dev Given a token Id, returns a byte array that is supposed to be converted into string. + function getMetadata(uint256 _tokenId, string memory) public view returns (bytes32[4] memory buffer, uint256 count) { + if (_tokenId == 1) { + buffer[0] = "Hello World! :D"; + count = 15; + } else if (_tokenId == 2) { + buffer[0] = "I would definitely choose a medi"; + buffer[1] = "um length string."; + count = 49; + } else if (_tokenId == 3) { + buffer[0] = "Lorem ipsum dolor sit amet, mi e"; + buffer[1] = "st accumsan dapibus augue lorem,"; + buffer[2] = " tristique vestibulum id, libero"; + buffer[3] = " suscipit varius sapien aliquam."; + count = 128; + } + } +} + + + + + + + + + + + + + + + +/// @title Auction Core +/// @dev Contains models, variables, and internal methods for the auction. +/// @notice We omit a fallback function to prevent accidental sends to this contract. +contract ClockAuctionBase { + + // Represents an auction on an NFT + struct Auction { + // Current owner of NFT + address seller; + // Price (in wei) at beginning of auction + uint128 startingPrice; + // Price (in wei) at end of auction + uint128 endingPrice; + // Duration (in seconds) of auction + uint64 duration; + // Time when auction started + // NOTE: 0 if this auction has been concluded + uint64 startedAt; + } + + // Reference to contract tracking NFT ownership + ERC721 public nonFungibleContract; + + // Cut owner takes on each auction, measured in basis points (1/100 of a percent). + // Values 0-10,000 map to 0%-100% + uint256 public ownerCut; + + // Map from token ID to their corresponding auction. + mapping (uint256 => Auction) tokenIdToAuction; + + event AuctionCreated(uint256 tokenId, uint256 startingPrice, uint256 endingPrice, uint256 duration); + event AuctionSuccessful(uint256 tokenId, uint256 totalPrice, address winner); + event AuctionCancelled(uint256 tokenId); + + /// @dev Returns true if the claimant owns the token. + /// @param _claimant - Address claiming to own the token. + /// @param _tokenId - ID of token whose ownership to verify. + function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { + return (nonFungibleContract.ownerOf(_tokenId) == _claimant); + } + + /// @dev Escrows the NFT, assigning ownership to this contract. + /// Throws if the escrow fails. + /// @param _owner - Current owner address of token to escrow. + /// @param _tokenId - ID of token whose approval to verify. + function _escrow(address _owner, uint256 _tokenId) internal { + // it will throw if transfer fails + nonFungibleContract.transferFrom(_owner, address(this), _tokenId); + } + + /// @dev Transfers an NFT owned by this contract to another address. + /// Returns true if the transfer succeeds. + /// @param _receiver - Address to transfer NFT to. + /// @param _tokenId - ID of token to transfer. + function _transfer(address _receiver, uint256 _tokenId) internal { + // it will throw if transfer fails + nonFungibleContract.transfer(_receiver, _tokenId); + } + + /// @dev Adds an auction to the list of open auctions. Also fires the + /// AuctionCreated event. + /// @param _tokenId The ID of the token to be put on auction. + /// @param _auction Auction to add. + function _addAuction(uint256 _tokenId, Auction memory _auction) internal { + // Require that all auctions have a duration of + // at least one minute. (Keeps our math from getting hairy!) + require(_auction.duration >= 1 minutes); + + tokenIdToAuction[_tokenId] = _auction; + + emit AuctionCreated( + uint256(_tokenId), + uint256(_auction.startingPrice), + uint256(_auction.endingPrice), + uint256(_auction.duration) + ); + } + + /// @dev Cancels an auction unconditionally. + function _cancelAuction(uint256 _tokenId, address _seller) internal { + _removeAuction(_tokenId); + _transfer(_seller, _tokenId); + emit AuctionCancelled(_tokenId); + } + + /// @dev Computes the price and transfers winnings. + /// Does NOT transfer ownership of token. + function _bid(uint256 _tokenId, uint256 _bidAmount) + internal + returns (uint256) + { + // Get a reference to the auction struct + Auction storage auction = tokenIdToAuction[_tokenId]; + + // Explicitly check that this auction is currently live. + // (Because of how Ethereum mappings work, we can't just count + // on the lookup above failing. An invalid _tokenId will just + // return an auction object that is all zeros.) + require(_isOnAuction(auction)); + + // Check that the bid is greater than or equal to the current price + uint256 price = _currentPrice(auction); + require(_bidAmount >= price); + + // Grab a reference to the seller before the auction struct + // gets deleted. + address seller = auction.seller; + + // The bid is good! Remove the auction before sending the fees + // to the sender so we can't have a reentrancy attack. + _removeAuction(_tokenId); + + // Transfer proceeds to seller (if there are any!) + if (price > 0) { + // Calculate the auctioneer's cut. + // (NOTE: _computeCut() is guaranteed to return a + // value <= price, so this subtraction can't go negative.) + uint256 auctioneerCut = _computeCut(price); + uint256 sellerProceeds = price - auctioneerCut; + + // NOTE: Doing a transfer() in the middle of a complex + // method like this is generally discouraged because of + // reentrancy attacks and DoS attacks if the seller is + // a contract with an invalid fallback function. We explicitly + // guard against reentrancy attacks by removing the auction + // before calling transfer(), and the only thing the seller + // can DoS is the sale of their own asset! (And if it's an + // accident, they can call cancelAuction(). ) + seller.transfer(sellerProceeds); + } + + // Calculate any excess funds included with the bid. If the excess + // is anything worth worrying about, transfer it back to bidder. + // NOTE: We checked above that the bid amount is greater than or + // equal to the price so this cannot underflow. + uint256 bidExcess = _bidAmount - price; + + // Return the funds. Similar to the previous transfer, this is + // not susceptible to a re-entry attack because the auction is + // removed before any transfers occur. + msg.sender.transfer(bidExcess); + + // Tell the world! + emit AuctionSuccessful(_tokenId, price, msg.sender); + + return price; + } + + /// @dev Removes an auction from the list of open auctions. + /// @param _tokenId - ID of NFT on auction. + function _removeAuction(uint256 _tokenId) internal { + delete tokenIdToAuction[_tokenId]; + } + + /// @dev Returns true if the NFT is on auction. + /// @param _auction - Auction to check. + function _isOnAuction(Auction storage _auction) internal view returns (bool) { + return (_auction.startedAt > 0); + } + + /// @dev Returns current price of an NFT on auction. Broken into two + /// functions (this one, that computes the duration from the auction + /// structure, and the other that does the price computation) so we + /// can easily test that the price computation works correctly. + function _currentPrice(Auction storage _auction) + internal + view + returns (uint256) + { + uint256 secondsPassed = 0; + + // A bit of insurance against negative values (or wraparound). + // Probably not necessary (since Ethereum guarnatees that the + // now variable doesn't ever go backwards). + if (now > _auction.startedAt) { + secondsPassed = now - _auction.startedAt; + } + + return _computeCurrentPrice( + _auction.startingPrice, + _auction.endingPrice, + _auction.duration, + secondsPassed + ); + } + + /// @dev Computes the current price of an auction. Factored out + /// from _currentPrice so we can run extensive unit tests. + /// When testing, make this function public and turn on + /// `Current price computation` test suite. + function _computeCurrentPrice( + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration, + uint256 _secondsPassed + ) + internal + pure + returns (uint256) + { + // NOTE: We don't use SafeMath (or similar) in this function because + // all of our public functions carefully cap the maximum values for + // time (at 64-bits) and currency (at 128-bits). _duration is + // also known to be non-zero (see the require() statement in + // _addAuction()) + if (_secondsPassed >= _duration) { + // We've reached the end of the dynamic pricing portion + // of the auction, just return the end price. + return _endingPrice; + } else { + // Starting price can be higher than ending price (and often is!), so + // this delta can be negative. + int256 totalPriceChange = int256(_endingPrice) - int256(_startingPrice); + + // This multiplication can't overflow, _secondsPassed will easily fit within + // 64-bits, and totalPriceChange will easily fit within 128-bits, their product + // will always fit within 256-bits. + int256 currentPriceChange = totalPriceChange * int256(_secondsPassed) / int256(_duration); + + // currentPriceChange can be negative, but if so, will have a magnitude + // less that _startingPrice. Thus, this result will always end up positive. + int256 currentPrice = int256(_startingPrice) + currentPriceChange; + + return uint256(currentPrice); + } + } + + /// @dev Computes owner's cut of a sale. + /// @param _price - Sale price of NFT. + function _computeCut(uint256 _price) internal view returns (uint256) { + // NOTE: We don't use SafeMath (or similar) in this function because + // all of our entry functions carefully cap the maximum values for + // currency (at 128-bits), and ownerCut <= 10000 (see the require() + // statement in the ClockAuction constructor). The result of this + // function is always guaranteed to be <= _price. + return _price * ownerCut / 10000; + } + +} + + + + + + + +/** + * @title Pausable + * @dev Base contract which allows children to implement an emergency stop mechanism. + */ +contract Pausable is Ownable { + event Pause(); + event Unpause(); + + bool public paused = false; + + + /** + * @dev modifier to allow actions only when the contract IS paused + */ + modifier whenNotPaused() { + require(!paused); + _; + } + + /** + * @dev modifier to allow actions only when the contract IS NOT paused + */ + modifier whenPaused { + require(paused); + _; + } + + /** + * @dev called by the owner to pause, triggers stopped state + */ + function pause() onlyOwner whenNotPaused public returns (bool) { + paused = true; + emit Pause(); + return true; + } + + /** + * @dev called by the owner to unpause, returns to normal state + */ + function unpause() onlyOwner whenPaused public returns (bool) { + paused = false; + emit Unpause(); + return true; + } +} + + +/// @title Clock auction for non-fungible tokens. +/// @notice We omit a fallback function to prevent accidental sends to this contract. +contract ClockAuction is Pausable, ClockAuctionBase { + + /// @dev The ERC-165 interface signature for ERC-721. + /// Ref: https://github.com/ethereum/EIPs/issues/165 + /// Ref: https://github.com/ethereum/EIPs/issues/721 + bytes4 constant InterfaceSignature_ERC721 = bytes4(0x9a20483d); + + /// @dev Constructor creates a reference to the NFT ownership contract + /// and verifies the owner cut is in the valid range. + /// @param _nftAddress - address of a deployed contract implementing + /// the Nonfungible Interface. + /// @param _cut - percent cut the owner takes on each auction, must be + /// between 0-10,000. + constructor(address _nftAddress, uint256 _cut) public { + require(_cut <= 10000); + ownerCut = _cut; + + ERC721 candidateContract = ERC721(_nftAddress); + require(candidateContract.supportsInterface(InterfaceSignature_ERC721)); + nonFungibleContract = candidateContract; + } + + /// @dev Remove all Ether from the contract, which is the owner's cuts + /// as well as any Ether sent directly to the contract address. + /// Always transfers to the NFT contract, but can be called either by + /// the owner or the NFT contract. + function withdrawBalance() external { + address nftAddress = address(uint160(address(nonFungibleContract))); + + require( + msg.sender == owner || + msg.sender == nftAddress + ); + // We are using this boolean method to make sure that even if one fails it will still work + bool res = nftAddress.send(address(this).balance); + } + + /// @dev Creates and begins a new auction. + /// @param _tokenId - ID of token to auction, sender must be owner. + /// @param _startingPrice - Price of item (in wei) at beginning of auction. + /// @param _endingPrice - Price of item (in wei) at end of auction. + /// @param _duration - Length of time to move between starting + /// price and ending price (in seconds). + /// @param _seller - Seller, if not the message sender + function createAuction( + uint256 _tokenId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration, + address _seller + ) + external + whenNotPaused + { + // Sanity check that no inputs overflow how many bits we've allocated + // to store them in the auction struct. + require(_startingPrice == uint256(uint128(_startingPrice))); + require(_endingPrice == uint256(uint128(_endingPrice))); + require(_duration == uint256(uint64(_duration))); + + require(_owns(msg.sender, _tokenId)); + _escrow(msg.sender, _tokenId); + Auction memory auction = Auction( + _seller, + uint128(_startingPrice), + uint128(_endingPrice), + uint64(_duration), + uint64(now) + ); + _addAuction(_tokenId, auction); + } + + /// @dev Bids on an open auction, completing the auction and transferring + /// ownership of the NFT if enough Ether is supplied. + /// @param _tokenId - ID of token to bid on. + function bid(uint256 _tokenId) + external + payable + whenNotPaused + { + // _bid will throw if the bid or funds transfer fails + _bid(_tokenId, msg.value); + _transfer(msg.sender, _tokenId); + } + + /// @dev Cancels an auction that hasn't been won yet. + /// Returns the NFT to original owner. + /// @notice This is a state-modifying function that can + /// be called while the contract is paused. + /// @param _tokenId - ID of token on auction + function cancelAuction(uint256 _tokenId) + external + { + Auction storage auction = tokenIdToAuction[_tokenId]; + require(_isOnAuction(auction)); + address seller = auction.seller; + require(msg.sender == seller); + _cancelAuction(_tokenId, seller); + } + + /// @dev Cancels an auction when the contract is paused. + /// Only the owner may do this, and NFTs are returned to + /// the seller. This should only be used in emergencies. + /// @param _tokenId - ID of the NFT on auction to cancel. + function cancelAuctionWhenPaused(uint256 _tokenId) + whenPaused + onlyOwner + external + { + Auction storage auction = tokenIdToAuction[_tokenId]; + require(_isOnAuction(auction)); + _cancelAuction(_tokenId, auction.seller); + } + + /// @dev Returns auction info for an NFT on auction. + /// @param _tokenId - ID of NFT on auction. + function getAuction(uint256 _tokenId) + external + view + returns + ( + address seller, + uint256 startingPrice, + uint256 endingPrice, + uint256 duration, + uint256 startedAt + ) { + Auction storage auction = tokenIdToAuction[_tokenId]; + require(_isOnAuction(auction)); + return ( + auction.seller, + auction.startingPrice, + auction.endingPrice, + auction.duration, + auction.startedAt + ); + } + + /// @dev Returns the current price of an auction. + /// @param _tokenId - ID of the token price we are checking. + function getCurrentPrice(uint256 _tokenId) + external + view + returns (uint256) + { + Auction storage auction = tokenIdToAuction[_tokenId]; + require(_isOnAuction(auction)); + return _currentPrice(auction); + } + +} + + +/// @title Reverse auction modified for siring +/// @notice We omit a fallback function to prevent accidental sends to this contract. +contract SiringClockAuction is ClockAuction { + + // @dev Sanity check that allows us to ensure that we are pointing to the + // right auction in our setSiringAuctionAddress() call. + bool public isSiringClockAuction = true; + + // Delegate constructor + constructor(address _nftAddr, uint256 _cut) public + ClockAuction(_nftAddr, _cut) {} + + /// @dev Creates and begins a new auction. Since this function is wrapped, + /// require sender to be KittyCore contract. + /// @param _tokenId - ID of token to auction, sender must be owner. + /// @param _startingPrice - Price of item (in wei) at beginning of auction. + /// @param _endingPrice - Price of item (in wei) at end of auction. + /// @param _duration - Length of auction (in seconds). + /// @param _seller - Seller, if not the message sender + function createAuction( + uint256 _tokenId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration, + address _seller + ) + external + { + // Sanity check that no inputs overflow how many bits we've allocated + // to store them in the auction struct. + require(_startingPrice == uint256(uint128(_startingPrice))); + require(_endingPrice == uint256(uint128(_endingPrice))); + require(_duration == uint256(uint64(_duration))); + + require(msg.sender == address(nonFungibleContract)); + _escrow(_seller, _tokenId); + Auction memory auction = Auction( + _seller, + uint128(_startingPrice), + uint128(_endingPrice), + uint64(_duration), + uint64(now) + ); + _addAuction(_tokenId, auction); + } + + /// @dev Places a bid for siring. Requires the sender + /// is the KittyCore contract because all bid methods + /// should be wrapped. Also returns the kitty to the + /// seller rather than the winner. + function bid(uint256 _tokenId) + external + payable + { + require(msg.sender == address(nonFungibleContract)); + address seller = tokenIdToAuction[_tokenId].seller; + // _bid checks that token ID is valid and will throw if bid fails + _bid(_tokenId, msg.value); + // We transfer the kitty back to the seller, the winner will get + // the offspring + _transfer(seller, _tokenId); + } + +} + + + + + +/// @title Clock auction modified for sale of kitties +/// @notice We omit a fallback function to prevent accidental sends to this contract. +contract SaleClockAuction is ClockAuction { + + // @dev Sanity check that allows us to ensure that we are pointing to the + // right auction in our setSaleAuctionAddress() call. + bool public isSaleClockAuction = true; + + // Tracks last 5 sale price of gen0 kitty sales + uint256 public gen0SaleCount; + uint256[5] public lastGen0SalePrices; + + // Delegate constructor + constructor(address _nftAddr, uint256 _cut) public + ClockAuction(_nftAddr, _cut) {} + + /// @dev Creates and begins a new auction. + /// @param _tokenId - ID of token to auction, sender must be owner. + /// @param _startingPrice - Price of item (in wei) at beginning of auction. + /// @param _endingPrice - Price of item (in wei) at end of auction. + /// @param _duration - Length of auction (in seconds). + /// @param _seller - Seller, if not the message sender + function createAuction( + uint256 _tokenId, + uint256 _startingPrice, + uint256 _endingPrice, + uint256 _duration, + address _seller + ) + external + { + // Sanity check that no inputs overflow how many bits we've allocated + // to store them in the auction struct. + require(_startingPrice == uint256(uint128(_startingPrice))); + require(_endingPrice == uint256(uint128(_endingPrice))); + require(_duration == uint256(uint64(_duration))); + + require(msg.sender == address(nonFungibleContract)); + _escrow(_seller, _tokenId); + Auction memory auction = Auction( + _seller, + uint128(_startingPrice), + uint128(_endingPrice), + uint64(_duration), + uint64(now) + ); + _addAuction(_tokenId, auction); + } + + /// @dev Updates lastSalePrice if seller is the nft contract + /// Otherwise, works the same as default bid method. + function bid(uint256 _tokenId) + external + payable + { + // _bid verifies token ID size + address seller = tokenIdToAuction[_tokenId].seller; + uint256 price = _bid(_tokenId, msg.value); + _transfer(msg.sender, _tokenId); + + // If not a gen0 auction, exit + if (seller == address(nonFungibleContract)) { + // Track gen0 sale prices + lastGen0SalePrices[gen0SaleCount % 5] = price; + gen0SaleCount++; + } + } + + function averageGen0SalePrice() external view returns (uint256) { + uint256 sum = 0; + for (uint256 i = 0; i < 5; i++) { + sum += lastGen0SalePrices[i]; + } + return sum / 5; + } + +} + + + + + + + diff --git a/src/test/resources/soliditycode_v0.4.25/contractScenario012.sol b/src/test/resources/soliditycode_v0.4.25/contractScenario012.sol new file mode 100644 index 00000000000..81f64134298 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractScenario012.sol @@ -0,0 +1,57 @@ +//pragma solidity ^0.4.0; +contract PayTest { + +uint256 public n; +constructor() payable public{ +n = 0; +} + +function nPlusOne() public{ +n = n+1; +} + +//get current contract balance +function getBalance() payable public returns (uint) { +return address(this).balance; +} + +function getSenderBalance() public view returns(address, uint) { +return (msg.sender, msg.sender.balance); +} + +address public user; + +//deposit 1 coin to msg.sender +function depositOneCoin() payable public returns(bool success){ +return msg.sender.send(1); +} + +// function transferOneCoin() payable public returns(){ +// address(msg.sender).transfer(1); +// } + +// function depositOneCoin() payable public returns(address addr, uint amount, bool success){ +// return (msg.sender, msg.value, msg.sender.send(1)); +// } + +//deposit coin to msg.sender +function deposit(uint256 money) payable public returns(bool success){ +return msg.sender.send(money); +} +// function deposit(uint money) payable public returns(address addr, uint amount, bool success){ +// return (msg.sender, msg.value, msg.sender.send(money)); +// } + +// function () payable { +// msg.sender.send(1); +// } + +function sendToAddress(address _receiver) payable public{ +_receiver.transfer(msg.value); +} + +function sendToAddress2(address _receiver) payable public{ +_receiver.transfer(5); +} + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractScenario013.sol b/src/test/resources/soliditycode_v0.4.25/contractScenario013.sol new file mode 100644 index 00000000000..b91085d018e --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractScenario013.sol @@ -0,0 +1,8 @@ +//pragma solidity ^0.4.0; +contract timetest { + +function time() public{ +require(1 trx == 1000000 sun); + +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractScenario014.sol b/src/test/resources/soliditycode_v0.4.25/contractScenario014.sol new file mode 100644 index 00000000000..0e00a8f7f9b --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractScenario014.sol @@ -0,0 +1,34 @@ +//pragma solidity ^0.4.0; +contract Contract1 { + constructor() public payable{} + function send5SunToReceiver(address _receiver) payable public{ + _receiver.transfer(5); + } +} +contract contract2 { + address public payContract; + + constructor(address _add) payable public{ + payContract = _add; + } + + function triggerContract1(address _receiver) payable public{ + payContract.call(abi.encodeWithSignature("send5SunToReceiver(address)",_receiver)); + } + + function triggerContract1ButRevert(address _receiver) payable public{ + payContract.call(abi.encodeWithSignature("send5SunToReceiver(address)",_receiver)); + require(1 == 2); + } + +} +contract contract3 { + address public payContract; + constructor(address _add) payable public{ + payContract = _add; + } + + function triggerContract2(address _receiver) payable public{ + payContract.call(abi.encodeWithSignature("triggerContract1(address)",_receiver)); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTest.sol b/src/test/resources/soliditycode_v0.4.25/contractTest.sol new file mode 100644 index 00000000000..d6c5f34af2d --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTest.sol @@ -0,0 +1,19 @@ +//pragma solidity ^0.4.4; + +contract Test{ + +function a() returns (uint){ + +uint256 count = 0; + +for (uint256 i = 1; i > 0; i++) { + +count++; + +} + +return count; + +} + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractToMathedFeed.sol b/src/test/resources/soliditycode_v0.4.25/contractToMathedFeed.sol new file mode 100644 index 00000000000..7cbfddfc657 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractToMathedFeed.sol @@ -0,0 +1,19 @@ +//pragma solidity ^0.4.0; + +contract ToMathedFeed { + uint public i=1; + function ToMathed(uint value) { + i=value; + } +} + +contract ToMathedUseINContract { + function ToMathedIUseNR(address a,uint256 n) returns(bool){ + address payContract=a; + return payContract.call(bytes4(keccak256("ToMathedNot(uint256)")),n); + } + function ToMathedIUseNRE(address a,uint256 value) returns(bool){ + address payContract=a; + return payContract.call(bytes4(keccak256("ToMathed(uint256)")),value); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken001.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken001.sol new file mode 100644 index 00000000000..a7649149263 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken001.sol @@ -0,0 +1,30 @@ +//pragma solidity ^0.4.24; + + contract tokenTest{ + trcToken idCon = 0; + uint256 tokenValueCon=0; + uint256 callValueCon = 0; + + // positive case + function TransferTokenTo(address toAddress, trcToken id,uint256 amount) public payable{ + //trcToken id = 0x74657374546f6b656e; + toAddress.transferToken(amount,id); + } + + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ + trcToken id = msg.tokenid; + uint256 tokenValue = msg.tokenvalue; + uint256 callValue = msg.value; + return (id, tokenValue, callValue); + } + + constructor() public payable { + idCon = msg.tokenid; + tokenValueCon = msg.tokenvalue; + callValueCon = msg.value; + } + + function getResultInCon() public payable returns(trcToken, uint256, uint256) { + return (idCon, tokenValueCon, callValueCon); + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken002.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken002.sol new file mode 100644 index 00000000000..a7649149263 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken002.sol @@ -0,0 +1,30 @@ +//pragma solidity ^0.4.24; + + contract tokenTest{ + trcToken idCon = 0; + uint256 tokenValueCon=0; + uint256 callValueCon = 0; + + // positive case + function TransferTokenTo(address toAddress, trcToken id,uint256 amount) public payable{ + //trcToken id = 0x74657374546f6b656e; + toAddress.transferToken(amount,id); + } + + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ + trcToken id = msg.tokenid; + uint256 tokenValue = msg.tokenvalue; + uint256 callValue = msg.value; + return (id, tokenValue, callValue); + } + + constructor() public payable { + idCon = msg.tokenid; + tokenValueCon = msg.tokenvalue; + callValueCon = msg.value; + } + + function getResultInCon() public payable returns(trcToken, uint256, uint256) { + return (idCon, tokenValueCon, callValueCon); + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken003.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken003.sol new file mode 100644 index 00000000000..924513518ea --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken003.sol @@ -0,0 +1,16 @@ +//pragma solidity ^0.4.24; + + contract tokenTest{ + constructor() public payable{} + // positive case + function TransferTokenTo(address toAddress, trcToken id,uint256 amount) public payable{ + //trcToken id = 0x74657374546f6b656e; + toAddress.transferToken(amount,id); + } + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ + trcToken id = msg.tokenid; + uint256 tokenValue = msg.tokenvalue; + uint256 callValue = msg.value; + return (id, tokenValue, callValue); + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken005.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken005.sol new file mode 100644 index 00000000000..924513518ea --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken005.sol @@ -0,0 +1,16 @@ +//pragma solidity ^0.4.24; + + contract tokenTest{ + constructor() public payable{} + // positive case + function TransferTokenTo(address toAddress, trcToken id,uint256 amount) public payable{ + //trcToken id = 0x74657374546f6b656e; + toAddress.transferToken(amount,id); + } + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ + trcToken id = msg.tokenid; + uint256 tokenValue = msg.tokenvalue; + uint256 callValue = msg.value; + return (id, tokenValue, callValue); + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken011.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken011.sol new file mode 100644 index 00000000000..eee0510ccc3 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken011.sol @@ -0,0 +1,35 @@ +//pragma solidity ^0.4.24; +contract transferTokenContract { + constructor() payable public{} + function() payable public{} + function transferTokenTest(address toAddress, uint256 tokenValue, trcToken id) payable public { + toAddress.transferToken(tokenValue, id); + } + function transferTokenTestIDOverBigInteger(address toAddress) payable public { + toAddress.transferToken(1, 9223372036854775809); + } + function transferTokenTestValueRandomIdBigInteger(address toAddress) payable public { + toAddress.transferToken(1, 36893488147420103233); + } + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ + trcToken id = msg.tokenid; + uint256 value = msg.tokenvalue; + return (id, value); + } + function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ + trcToken id = 1000001; + return accountAddress.tokenBalance(id); + } + function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ + return toAddress.tokenBalance(tokenId); + } +} + + +contract Result { + event log(uint256,uint256,uint256); + constructor() payable public{} + function() payable public{ + emit log(msg.tokenid,msg.tokenvalue,msg.value); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken012.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken012.sol new file mode 100644 index 00000000000..99bb82c48f2 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken012.sol @@ -0,0 +1,26 @@ +//pragma solidity ^0.4.24; +contract transferTokenContract { + constructor() payable public{} + function() payable public{} + function transferTokenTest(address toAddress, uint256 tokenValue, trcToken id) payable public { + toAddress.transferToken(tokenValue, id); + } + function transferTokenTestIDOverBigInteger(address toAddress) payable public { + toAddress.transferToken(1, 9223372036854775809); + } + function transferTokenTestValueRandomIdBigInteger(address toAddress) payable public { + toAddress.transferToken(1, 36893488147420103233); + } + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ + trcToken id = msg.tokenid; + uint256 value = msg.tokenvalue; + return (id, value); + } + function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ + trcToken id = 1000001; + return accountAddress.tokenBalance(id); + } + function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ + return toAddress.tokenBalance(tokenId); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken014.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken014.sol new file mode 100644 index 00000000000..ada9432a02e --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken014.sol @@ -0,0 +1,34 @@ +//pragma solidity ^0.4.24; +contract transferTokenContract { + constructor() payable public{} + function() payable public{} + function transferTokenTest(address toAddress, uint256 tokenValue, trcToken id) payable public { + toAddress.transferToken(tokenValue, id); + } + function transferTokenTestIDOverBigInteger(address toAddress) payable public { + toAddress.transferToken(1, 9223372036854775809); + } + function transferTokenTestValueRandomIdBigInteger(address toAddress) payable public { + toAddress.transferToken(1, 36893488147420103233); + } + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ + trcToken id = msg.tokenid; + uint256 value = msg.tokenvalue; + return (id, value); + } + function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ + trcToken id = 1000001; + return accountAddress.tokenBalance(id); + } + function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ + return toAddress.tokenBalance(tokenId); + } +} + +contract Result { + event log(uint256,uint256,uint256); + constructor() payable public{} + function() payable external{ + emit log(msg.tokenid,msg.tokenvalue,msg.value); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken018.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken018.sol new file mode 100644 index 00000000000..99bb82c48f2 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken018.sol @@ -0,0 +1,26 @@ +//pragma solidity ^0.4.24; +contract transferTokenContract { + constructor() payable public{} + function() payable public{} + function transferTokenTest(address toAddress, uint256 tokenValue, trcToken id) payable public { + toAddress.transferToken(tokenValue, id); + } + function transferTokenTestIDOverBigInteger(address toAddress) payable public { + toAddress.transferToken(1, 9223372036854775809); + } + function transferTokenTestValueRandomIdBigInteger(address toAddress) payable public { + toAddress.transferToken(1, 36893488147420103233); + } + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ + trcToken id = msg.tokenid; + uint256 value = msg.tokenvalue; + return (id, value); + } + function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ + trcToken id = 1000001; + return accountAddress.tokenBalance(id); + } + function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ + return toAddress.tokenBalance(tokenId); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken023.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken023.sol new file mode 100644 index 00000000000..16551e2f177 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken023.sol @@ -0,0 +1,26 @@ +pragma solidity ^0.4.24; + + contract tokenTest{ + constructor() public payable{} + function TransferTokenTo(address toAddress, trcToken id,uint256 amount) public payable{ + toAddress.transferToken(amount,id); + } + } + +contract B{ + uint256 public flag = 0; + constructor() public payable {} + function() public payable { + flag = 1; +} + +} +pragma solidity ^0.4.24; +contract C{ + uint256 public flag = 0; + constructor() public payable {} + function() public payable { + //flag = 1; +} + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken026.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken026.sol new file mode 100644 index 00000000000..a45d885bbb4 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken026.sol @@ -0,0 +1,30 @@ +pragma solidity ^0.4.24; + +contract token{ + constructor() payable public{} + function() payable public{} + function testInCall(address callBAddress,address callCAddress, address toAddress ,uint256 amount,trcToken id) payable public{ + callBAddress.call(bytes4(keccak256("transC(address,address,uint256,trcToken)")),callCAddress,toAddress,amount,id); + } + function testIndelegateCall(address callBddress,address callAddressC, address toAddress,uint256 amount, trcToken id) payable public{ + callBddress.delegatecall(bytes4(keccak256("transC(address,address,uint256,trcToken)")),callAddressC,toAddress,amount,id); + } + } + + + +contract B{ + constructor() public payable{} + function() public payable{} + function transC(address callCAddress,address toAddress,uint256 amount, trcToken id) payable public{ + callCAddress.call(bytes4(keccak256("trans(address,uint256,trcToken)")),toAddress,amount,id); + } +} +contract C{ + constructor() payable public{} + function() payable public{} + function trans(address toAddress,uint256 amount, trcToken id) payable public{ + toAddress.transferToken(amount,id); + } + +} diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken027.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken027.sol new file mode 100644 index 00000000000..a45d885bbb4 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken027.sol @@ -0,0 +1,30 @@ +pragma solidity ^0.4.24; + +contract token{ + constructor() payable public{} + function() payable public{} + function testInCall(address callBAddress,address callCAddress, address toAddress ,uint256 amount,trcToken id) payable public{ + callBAddress.call(bytes4(keccak256("transC(address,address,uint256,trcToken)")),callCAddress,toAddress,amount,id); + } + function testIndelegateCall(address callBddress,address callAddressC, address toAddress,uint256 amount, trcToken id) payable public{ + callBddress.delegatecall(bytes4(keccak256("transC(address,address,uint256,trcToken)")),callAddressC,toAddress,amount,id); + } + } + + + +contract B{ + constructor() public payable{} + function() public payable{} + function transC(address callCAddress,address toAddress,uint256 amount, trcToken id) payable public{ + callCAddress.call(bytes4(keccak256("trans(address,uint256,trcToken)")),toAddress,amount,id); + } +} +contract C{ + constructor() payable public{} + function() payable public{} + function trans(address toAddress,uint256 amount, trcToken id) payable public{ + toAddress.transferToken(amount,id); + } + +} diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken028.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken028.sol new file mode 100644 index 00000000000..36dad7847a2 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken028.sol @@ -0,0 +1,25 @@ +pragma solidity ^0.4.24; + +contract token{ + uint256 public a=1; + constructor() public payable{} + function tokenBalanceWithSameName(trcToken id) public payable{ + B b= new B(); + a= b.tokenBalance(id); + } + function getA() public returns(uint256){ + return a; + } +} + + +contract B{ + uint256 public flag =0; + constructor() public payable{} + function() public payable{} + function tokenBalance(trcToken id) payable public returns(uint256){ + flag =9; + return flag; + } + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken029.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken029.sol new file mode 100644 index 00000000000..93a79a6f774 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken029.sol @@ -0,0 +1,24 @@ +pragma solidity ^0.4.24; + +contract token{ + address public a; + constructor() public payable{} + function transferTokenWithSameName(trcToken id,uint256 amount) public payable{ + B b= new B(); + b.transferToken(amount,id); + a= address(b); + } +} + + +contract B{ + uint256 public flag =0; + constructor() public payable{} + function() public payable{} + function transferToken(uint256 amount, trcToken id) payable public returns(bool){ + flag =9; + } + function getFlag() public view returns (uint256){ + return flag; + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken030.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken030.sol new file mode 100644 index 00000000000..d82c6ab6928 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken030.sol @@ -0,0 +1,18 @@ +pragma solidity ^0.4.24; + + contract token{ + constructor() public payable{} + + // 4)suicide也会转移token + // 所有token,trx均被转移到toAddress, + // 若toAddress为合约地址本身,则所有token,trx均被烧掉进黑洞 + function kill(address toAddress) payable public{ + selfdestruct(toAddress); + } + + } + +contract B{ + constructor() public payable {} + function() public payable {} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken031.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken031.sol new file mode 100644 index 00000000000..d82c6ab6928 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken031.sol @@ -0,0 +1,18 @@ +pragma solidity ^0.4.24; + + contract token{ + constructor() public payable{} + + // 4)suicide也会转移token + // 所有token,trx均被转移到toAddress, + // 若toAddress为合约地址本身,则所有token,trx均被烧掉进黑洞 + function kill(address toAddress) payable public{ + selfdestruct(toAddress); + } + + } + +contract B{ + constructor() public payable {} + function() public payable {} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken034.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken034.sol new file mode 100644 index 00000000000..03afab38850 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken034.sol @@ -0,0 +1,23 @@ +pragma solidity ^0.4.24; + + contract token{ + + // 2. 异常测试 + // 1)revert, 金额回退 + function failTransferTokenRevert(address toAddress,uint256 amount, trcToken id) public payable{ + toAddress.transferToken(amount,id); + require(1==2); + } + + // 2)Error, 金额回退, fee limit 扣光 + function failTransferTokenError(address toAddress,uint256 amount, trcToken id) public payable{ + toAddress.transferToken(amount,id); + assert(1==2); + } + + } + contract B{ + uint256 public flag = 0; + constructor() public payable {} + function() public payable {} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken035.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken035.sol new file mode 100644 index 00000000000..03afab38850 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken035.sol @@ -0,0 +1,23 @@ +pragma solidity ^0.4.24; + + contract token{ + + // 2. 异常测试 + // 1)revert, 金额回退 + function failTransferTokenRevert(address toAddress,uint256 amount, trcToken id) public payable{ + toAddress.transferToken(amount,id); + require(1==2); + } + + // 2)Error, 金额回退, fee limit 扣光 + function failTransferTokenError(address toAddress,uint256 amount, trcToken id) public payable{ + toAddress.transferToken(amount,id); + assert(1==2); + } + + } + contract B{ + uint256 public flag = 0; + constructor() public payable {} + function() public payable {} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken036.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken036.sol new file mode 100644 index 00000000000..b9c81f8cd59 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken036.sol @@ -0,0 +1,65 @@ +pragma solidity ^0.4.24; +contract IllegalDecorate { +constructor() payable public{} +function() payable public{} +event log(uint256); +function transferTokenWithPure(address toAddress, uint256 tokenValue) public payable { +emit log(msg.value); +emit log(msg.tokenvalue); +emit log(msg.tokenid); +toAddress.transferToken(msg.tokenvalue, msg.tokenid); +toAddress.transfer(msg.value); +} +} + +contract IllegalDecorate1 { +constructor() payable public{} +function() payable public{} +event log(uint256); +function transferTokenWithConstant(address toAddress, uint256 tokenValue) public constant { +emit log(msg.value); +emit log(msg.tokenvalue); +emit log(msg.tokenid); +toAddress.transferToken(msg.tokenvalue, msg.tokenid); +toAddress.transfer(msg.value); +} +} + +contract IllegalDecorate2 { +constructor() payable public{} +function() payable public{} +event log(uint256); +function transferTokenWithView(address toAddress, uint256 tokenValue) public view { +emit log(msg.value); +emit log(msg.tokenvalue); +emit log(msg.tokenid); +toAddress.transferToken(msg.tokenvalue, msg.tokenid); +toAddress.transfer(msg.value); +} +} + +contract IllegalDecorate3 { +event log(uint256); +constructor() payable public{} +function() payable public{} +function transferTokenWithOutPayable(address toAddress, uint256 tokenValue) public { +emit log(msg.value); +emit log(msg.tokenvalue); +emit log(msg.tokenid); +toAddress.transferToken(msg.tokenvalue, msg.tokenid); +toAddress.transfer(msg.value); +} +} + +contract IllegalDecorate4 { +constructor() payable public{} +function() payable public{} +event log(uint256); +function transferTokenWithPure(address toAddress, uint256 tokenValue) public pure { +emit log(msg.value); +emit log(msg.tokenvalue); +emit log(msg.tokenid); +toAddress.transferToken(msg.tokenvalue, msg.tokenid); +toAddress.transfer(msg.value); +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken037.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken037.sol new file mode 100644 index 00000000000..ad19db9a3a6 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken037.sol @@ -0,0 +1,23 @@ +pragma solidity ^0.4.24; + +contract transferTrc10 { + function receive(address rec) public payable { + uint256 aamount=address(this).tokenBalance(msg.tokenid); + uint256 bamount=rec.tokenBalance(msg.tokenid); + require(msg.tokenvalue==aamount); + require(aamount==msg.tokenvalue); + rec.transferToken(aamount,msg.tokenid); + require(0==address(this).tokenBalance(msg.tokenid)); + require(bamount+aamount==rec.tokenBalance(msg.tokenid)); + require(rec.call(bytes4(keccak256("checkTrc10(uint256,trcToken,uint256)")),bamount+aamount,msg.tokenid,0)); + } +} + +contract receiveTrc10 { + function() public payable { + } + function checkTrc10(uint256 amount,trcToken tid,uint256 meamount) public{ + require(amount==address(this).tokenBalance(tid)); + require(meamount==msg.sender.tokenBalance(tid)); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken038.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken038.sol new file mode 100644 index 00000000000..5b1a0babe8b --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken038.sol @@ -0,0 +1,22 @@ +pragma solidity ^0.4.24; + +contract transferTrc10 { + function receive(address rec) public payable { + uint256 aamount=address(this).tokenBalance(msg.tokenid); + uint256 bamount=rec.tokenBalance(msg.tokenid); + require(msg.tokenvalue==aamount); + require(aamount==msg.tokenvalue); + rec.transferToken(aamount,msg.tokenid); + require(rec.call(bytes4(keccak256("AssertError()")))); + require(aamount==address(this).tokenBalance(msg.tokenid)); + require(bamount==rec.tokenBalance(msg.tokenid)); + } +} + +contract receiveTrc10 { + function() public payable { + } + function AssertError() public{ + assert(1==2); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken039.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken039.sol new file mode 100644 index 00000000000..7229e3aaa9a --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken039.sol @@ -0,0 +1,44 @@ +pragma solidity ^0.4.24; +/* + * 1. caller账户issue一个token + * 2. caller部署proxy, 传入1000 token,1000 trx + * 3. caller部署A + * 4. caller部署B + * 5. caller调用proxy中upgradetTo函数,传入A的地址 + * 6. caller调用proxy中不存在的trans(uint256,address,trcToken)函数,注意这时trcToken是无意义的,但也带上tokenid。address是任意另外某账户的地址 + * 7. 可以看到目标地址trx增长5,caller账户trx减少5 + * 8. caller调用proxy中upgradeTo函数,传入B的地址 + * 9. caller调用proxy中不存在的trans(uint256,address,trcToken)函数。 + * 10. 可以看到目标地址token增长5,caller账户token减少5 +*/ +contract Proxy { + constructor() payable public{} + address public implementation; + function upgradeTo(address _address) public { + implementation = _address; + } + function() payable public{ + address addr = implementation; + require(addr != address(0)); + assembly { + let freememstart := mload(0x40) + calldatacopy(freememstart, 0, calldatasize()) + let success := delegatecall(not(0), addr, freememstart, calldatasize(), freememstart, 0) + returndatacopy(freememstart, 0, returndatasize()) + switch success + case 0 { revert(freememstart, returndatasize()) } + default { return(freememstart, returndatasize()) } + } + } +} + +contract A { + function trans(uint256 amount, address toAddress, trcToken id) payable public { + toAddress.transfer(amount); + } +} +contract B{ + function trans(uint256 amount, address toAddress, trcToken id) payable public { + toAddress.transferToken(amount,id); + } +} diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken041.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken041.sol new file mode 100644 index 00000000000..f70ab112afe --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken041.sol @@ -0,0 +1,20 @@ +pragma solidity ^0.4.24; + + contract tokenTest{ + constructor() public payable{} + // positive case + function TransferTokenTo(address toAddress, trcToken id,uint256 amount) public payable{ + //trcToken id = 0x74657374546f6b656e; + toAddress.transferToken(amount,id); + } + } + +contract B{ + uint256 public flag = 0; + constructor() public payable {} + function() public payable {} + + function setFlag() public payable{ + flag = 1; + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken043.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken043.sol new file mode 100644 index 00000000000..eee0510ccc3 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken043.sol @@ -0,0 +1,35 @@ +//pragma solidity ^0.4.24; +contract transferTokenContract { + constructor() payable public{} + function() payable public{} + function transferTokenTest(address toAddress, uint256 tokenValue, trcToken id) payable public { + toAddress.transferToken(tokenValue, id); + } + function transferTokenTestIDOverBigInteger(address toAddress) payable public { + toAddress.transferToken(1, 9223372036854775809); + } + function transferTokenTestValueRandomIdBigInteger(address toAddress) payable public { + toAddress.transferToken(1, 36893488147420103233); + } + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ + trcToken id = msg.tokenid; + uint256 value = msg.tokenvalue; + return (id, value); + } + function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ + trcToken id = 1000001; + return accountAddress.tokenBalance(id); + } + function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ + return toAddress.tokenBalance(tokenId); + } +} + + +contract Result { + event log(uint256,uint256,uint256); + constructor() payable public{} + function() payable public{ + emit log(msg.tokenid,msg.tokenvalue,msg.value); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken048.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken048.sol new file mode 100644 index 00000000000..de2844608c0 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken048.sol @@ -0,0 +1,14 @@ +//pragma solidity ^0.4.24; + + contract Test { + event log(uint256); + function testMsgTokenValue() payable public returns(uint256 value) { + emit log(msg.tokenvalue); + return msg.tokenvalue; + } + + function testMsgValue() payable public returns(uint256 value) { + emit log(msg.value); + return msg.value; + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken049.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken049.sol new file mode 100644 index 00000000000..25b31a4ffd6 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken049.sol @@ -0,0 +1,10 @@ +//pragma solidity ^0.4.24; + + contract tokenTest{ + constructor() public payable{} + // positive case + function TransferTokenTo(address toAddress, trcToken id,uint256 amount) public payable{ + //trcToken id = 0x74657374546f6b656e; + toAddress.transferToken(amount,id); + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken050.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken050.sol new file mode 100644 index 00000000000..25b31a4ffd6 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken050.sol @@ -0,0 +1,10 @@ +//pragma solidity ^0.4.24; + + contract tokenTest{ + constructor() public payable{} + // positive case + function TransferTokenTo(address toAddress, trcToken id,uint256 amount) public payable{ + //trcToken id = 0x74657374546f6b656e; + toAddress.transferToken(amount,id); + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken051.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken051.sol new file mode 100644 index 00000000000..25b31a4ffd6 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken051.sol @@ -0,0 +1,10 @@ +//pragma solidity ^0.4.24; + + contract tokenTest{ + constructor() public payable{} + // positive case + function TransferTokenTo(address toAddress, trcToken id,uint256 amount) public payable{ + //trcToken id = 0x74657374546f6b656e; + toAddress.transferToken(amount,id); + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken052.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken052.sol new file mode 100644 index 00000000000..25b31a4ffd6 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken052.sol @@ -0,0 +1,10 @@ +//pragma solidity ^0.4.24; + + contract tokenTest{ + constructor() public payable{} + // positive case + function TransferTokenTo(address toAddress, trcToken id,uint256 amount) public payable{ + //trcToken id = 0x74657374546f6b656e; + toAddress.transferToken(amount,id); + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken054.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken054.sol new file mode 100644 index 00000000000..924513518ea --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken054.sol @@ -0,0 +1,16 @@ +//pragma solidity ^0.4.24; + + contract tokenTest{ + constructor() public payable{} + // positive case + function TransferTokenTo(address toAddress, trcToken id,uint256 amount) public payable{ + //trcToken id = 0x74657374546f6b656e; + toAddress.transferToken(amount,id); + } + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ + trcToken id = msg.tokenid; + uint256 tokenValue = msg.tokenvalue; + uint256 callValue = msg.value; + return (id, tokenValue, callValue); + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken055.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken055.sol new file mode 100644 index 00000000000..924513518ea --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken055.sol @@ -0,0 +1,16 @@ +//pragma solidity ^0.4.24; + + contract tokenTest{ + constructor() public payable{} + // positive case + function TransferTokenTo(address toAddress, trcToken id,uint256 amount) public payable{ + //trcToken id = 0x74657374546f6b656e; + toAddress.transferToken(amount,id); + } + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ + trcToken id = msg.tokenid; + uint256 tokenValue = msg.tokenvalue; + uint256 callValue = msg.value; + return (id, tokenValue, callValue); + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken060.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken060.sol new file mode 100644 index 00000000000..a7649149263 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken060.sol @@ -0,0 +1,30 @@ +//pragma solidity ^0.4.24; + + contract tokenTest{ + trcToken idCon = 0; + uint256 tokenValueCon=0; + uint256 callValueCon = 0; + + // positive case + function TransferTokenTo(address toAddress, trcToken id,uint256 amount) public payable{ + //trcToken id = 0x74657374546f6b656e; + toAddress.transferToken(amount,id); + } + + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ + trcToken id = msg.tokenid; + uint256 tokenValue = msg.tokenvalue; + uint256 callValue = msg.value; + return (id, tokenValue, callValue); + } + + constructor() public payable { + idCon = msg.tokenid; + tokenValueCon = msg.tokenvalue; + callValueCon = msg.value; + } + + function getResultInCon() public payable returns(trcToken, uint256, uint256) { + return (idCon, tokenValueCon, callValueCon); + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken061.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken061.sol new file mode 100644 index 00000000000..a7649149263 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken061.sol @@ -0,0 +1,30 @@ +//pragma solidity ^0.4.24; + + contract tokenTest{ + trcToken idCon = 0; + uint256 tokenValueCon=0; + uint256 callValueCon = 0; + + // positive case + function TransferTokenTo(address toAddress, trcToken id,uint256 amount) public payable{ + //trcToken id = 0x74657374546f6b656e; + toAddress.transferToken(amount,id); + } + + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ + trcToken id = msg.tokenid; + uint256 tokenValue = msg.tokenvalue; + uint256 callValue = msg.value; + return (id, tokenValue, callValue); + } + + constructor() public payable { + idCon = msg.tokenid; + tokenValueCon = msg.tokenvalue; + callValueCon = msg.value; + } + + function getResultInCon() public payable returns(trcToken, uint256, uint256) { + return (idCon, tokenValueCon, callValueCon); + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken064.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken064.sol new file mode 100644 index 00000000000..0378fd90cc1 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken064.sol @@ -0,0 +1,49 @@ +//pragma solidity ^0.4.24; +contract transferTokenContract { + constructor() payable public{} + function() payable public{} + function transferTokenTest(address toAddress, uint256 tokenValue, trcToken id) payable public { + toAddress.transferToken(tokenValue, id); + } + function transferTokenTestIDOverBigInteger(address toAddress) payable public { + toAddress.transferToken(1, 9223372036854775809); + } + function transferTokenTestValueRandomIdBigInteger(address toAddress) payable public { + toAddress.transferToken(1, 36893488147420103233); + } + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ + trcToken id = msg.tokenid; + uint256 value = msg.tokenvalue; + return (id, value); + } + function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ + trcToken id = 1000001; + return accountAddress.tokenBalance(id); + } + function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ + return toAddress.tokenBalance(tokenId); + } + function transferTokenTestValueMaxBigInteger(address toAddress) payable public { + toAddress.transferToken(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, 0); + } + function transferTokenTestValueOverBigInteger(address toAddress) payable public { + toAddress.transferToken(9223372036854775808, 1000001); + } + function transferTokenTestValueMaxLong(address toAddress) payable public { + toAddress.transferToken(9223372036854775807, 1000001); + } + function transferTokenTestValue0IdBigInteger(address toAddress) payable public { + toAddress.transferToken(0, 9223372036854775809); + } +} + + + + +contract Result { + event log(uint256,uint256,uint256); + constructor() payable public{} + function() payable public{ + emit log(msg.tokenid,msg.tokenvalue,msg.value); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken066.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken066.sol new file mode 100644 index 00000000000..eee0510ccc3 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken066.sol @@ -0,0 +1,35 @@ +//pragma solidity ^0.4.24; +contract transferTokenContract { + constructor() payable public{} + function() payable public{} + function transferTokenTest(address toAddress, uint256 tokenValue, trcToken id) payable public { + toAddress.transferToken(tokenValue, id); + } + function transferTokenTestIDOverBigInteger(address toAddress) payable public { + toAddress.transferToken(1, 9223372036854775809); + } + function transferTokenTestValueRandomIdBigInteger(address toAddress) payable public { + toAddress.transferToken(1, 36893488147420103233); + } + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ + trcToken id = msg.tokenid; + uint256 value = msg.tokenvalue; + return (id, value); + } + function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ + trcToken id = 1000001; + return accountAddress.tokenBalance(id); + } + function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ + return toAddress.tokenBalance(tokenId); + } +} + + +contract Result { + event log(uint256,uint256,uint256); + constructor() payable public{} + function() payable public{ + emit log(msg.tokenid,msg.tokenvalue,msg.value); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken067.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken067.sol new file mode 100644 index 00000000000..eee0510ccc3 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken067.sol @@ -0,0 +1,35 @@ +//pragma solidity ^0.4.24; +contract transferTokenContract { + constructor() payable public{} + function() payable public{} + function transferTokenTest(address toAddress, uint256 tokenValue, trcToken id) payable public { + toAddress.transferToken(tokenValue, id); + } + function transferTokenTestIDOverBigInteger(address toAddress) payable public { + toAddress.transferToken(1, 9223372036854775809); + } + function transferTokenTestValueRandomIdBigInteger(address toAddress) payable public { + toAddress.transferToken(1, 36893488147420103233); + } + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256){ + trcToken id = msg.tokenid; + uint256 value = msg.tokenvalue; + return (id, value); + } + function getTokenBalanceTest(address accountAddress) payable public returns (uint256){ + trcToken id = 1000001; + return accountAddress.tokenBalance(id); + } + function getTokenBalnce(address toAddress, trcToken tokenId) public payable returns(uint256){ + return toAddress.tokenBalance(tokenId); + } +} + + +contract Result { + event log(uint256,uint256,uint256); + constructor() payable public{} + function() payable public{ + emit log(msg.tokenid,msg.tokenvalue,msg.value); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken073.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken073.sol new file mode 100644 index 00000000000..b5b6d149565 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken073.sol @@ -0,0 +1,17 @@ +//pragma solidity ^0.4.0; + +contract Dest { + event logFallback(uint256 indexed, uint256 indexed, uint256 indexed); + event logGetToken(uint256 indexed, uint256 indexed, uint256 indexed, uint256); + + + function Dest() payable public {} + + function getToken(trcToken tokenId) payable { + logGetToken(msg.sender.tokenBalance(tokenId), msg.tokenid, msg.tokenvalue, msg.value); + } + + function () payable { + logFallback(msg.tokenid, msg.tokenvalue, msg.value); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken075.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken075.sol new file mode 100644 index 00000000000..dfcaf8c2a52 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken075.sol @@ -0,0 +1,26 @@ +//pragma solidity ^0.4.0; + +contract Dest { + event logFallback(uint256 indexed, uint256 indexed, uint256 indexed); + event logGetToken(uint256 indexed, uint256 indexed, uint256 indexed, uint256); + + function Dest() payable public {} + + function getToken(trcToken tokenId) payable { + logGetToken(msg.sender.tokenBalance(tokenId), msg.tokenid, msg.tokenvalue, msg.value); + } + + function getTokenLongMin() payable { + // long.min - 1000020 + logGetToken(msg.sender.tokenBalance(trcToken(-9223372036855775828)), msg.tokenid, msg.tokenvalue, msg.value); + } + + function getTokenLongMax() payable { + // long.max + 1000020 + logGetToken(msg.sender.tokenBalance(trcToken(9223372036855775827)), msg.tokenid, msg.tokenvalue, msg.value); + } + + function () payable { + logFallback(msg.tokenid, msg.tokenvalue, msg.value); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken076.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken076.sol new file mode 100644 index 00000000000..9de79a327c3 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken076.sol @@ -0,0 +1,19 @@ +//pragma solidity ^0.4.24; +contract Test { + address public origin; + address public sender; + bool public result1; + bool public result2; + function test() external { + origin = tx.origin; + sender = msg.sender; + result1 = msg.sender == tx.origin; // true + result2 = origin == sender; // true + } +function getResult1() public returns(bool){ + return result1; +} +function getResult2() public returns(bool){ + return result2; +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken077.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken077.sol new file mode 100644 index 00000000000..e110f24e2fc --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken077.sol @@ -0,0 +1,11 @@ +//pragma solidity ^0.4.24; + +contract trcToken077 { +function addressTest() public returns(bytes32 addressValue) { + assembly{ + let x := mload(0x40) //Find empty storage location using "free memory pointer" + mstore(x,address) //Place current contract address + addressValue := mload(x) + } + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken078.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken078.sol new file mode 100644 index 00000000000..4d51a365e14 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken078.sol @@ -0,0 +1,35 @@ +//pragma solidity ^0.4.24; +contract callerContract { + constructor() payable{} + function() payable{} + function sendToB(address called_address,address c) public payable{ + called_address.delegatecall(bytes4(keccak256("transferTo(address)")),c); + } + function sendToB2(address called_address,address c) public payable{ + called_address.call(bytes4(keccak256("transferTo(address)")),c); + } + function sendToB3(address called_address,address c) public payable{ + called_address.callcode(bytes4(keccak256("transferTo(address)")),c); + } +} + contract calledContract { + function() payable{} + constructor() payable {} + function transferTo(address toAddress)public payable{ + toAddress.transfer(5); + } + + function setIinC(address c) public payable{ + c.call.value(5)(bytes4(keccak256("setI()"))); + } + + } + contract c{ + address public origin; + address public sender; + constructor() public payable{} + event log(address,address); + function() payable public{ + emit log(tx.origin,msg.sender); + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken079.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken079.sol new file mode 100644 index 00000000000..924513518ea --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken079.sol @@ -0,0 +1,16 @@ +//pragma solidity ^0.4.24; + + contract tokenTest{ + constructor() public payable{} + // positive case + function TransferTokenTo(address toAddress, trcToken id,uint256 amount) public payable{ + //trcToken id = 0x74657374546f6b656e; + toAddress.transferToken(amount,id); + } + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ + trcToken id = msg.tokenid; + uint256 tokenValue = msg.tokenvalue; + uint256 callValue = msg.value; + return (id, tokenValue, callValue); + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcToken080.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcToken080.sol new file mode 100644 index 00000000000..a7649149263 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcToken080.sol @@ -0,0 +1,30 @@ +//pragma solidity ^0.4.24; + + contract tokenTest{ + trcToken idCon = 0; + uint256 tokenValueCon=0; + uint256 callValueCon = 0; + + // positive case + function TransferTokenTo(address toAddress, trcToken id,uint256 amount) public payable{ + //trcToken id = 0x74657374546f6b656e; + toAddress.transferToken(amount,id); + } + + function msgTokenValueAndTokenIdTest() public payable returns(trcToken, uint256, uint256){ + trcToken id = msg.tokenid; + uint256 tokenValue = msg.tokenvalue; + uint256 callValue = msg.value; + return (id, tokenValue, callValue); + } + + constructor() public payable { + idCon = msg.tokenid; + tokenValueCon = msg.tokenvalue; + callValueCon = msg.value; + } + + function getResultInCon() public payable returns(trcToken, uint256, uint256) { + return (idCon, tokenValueCon, callValueCon); + } + } \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractTrcTokenToOther.sol b/src/test/resources/soliditycode_v0.4.25/contractTrcTokenToOther.sol new file mode 100644 index 00000000000..e9ebd0ae865 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractTrcTokenToOther.sol @@ -0,0 +1,44 @@ +//pragma solidity ^0.4.24; + +contract ConvertType { + +constructor() payable public{} + +function() payable public{} + +// function trcTokenOnStorage(trcToken storage token) internal { // ERROR Storage location can only be given for array or struct types +// } + +function trcTokenToString(trcToken token) public constant returns(string r){ +// string s = token; // ERROR +// string s2 = string(token); // ERROR +} + +function trcTokenToUint256(trcToken token) public constant returns(uint256 r){ +uint256 u = token; // OK +uint256 u2 = uint256(token); // OK +r = u2; +} + +function trcTokenToAddress(trcToken token) public constant returns(address r){ +// address a = token; // ERROR +token = 0x1234567812345678123456781234567812345678123456781234567812345678; +address a2 = address(token); // OK +r = a2; +} + +function trcTokenToBytes(trcToken token) public constant returns(bytes r){ +// bytes b = token; // ERROR +// bytes b2 = bytes(token); // ERROR +} + +function trcTokenToBytes32(trcToken token) public constant returns(bytes32 r){ +// bytes32 b = token; // ERROR +bytes32 b2 = bytes32(token); // OK +r = b2; +} + +function trcTokenToArray(trcToken token) public constant returns(uint[] r){ +// uint[] a = token; // ERROR +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/contractUnknownException.sol b/src/test/resources/soliditycode_v0.4.25/contractUnknownException.sol new file mode 100644 index 00000000000..be8af8f7451 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/contractUnknownException.sol @@ -0,0 +1,65 @@ + pragma solidity ^0.4.24; + +contract testA { + constructor() public payable { + A a = (new A).value(10)(); + a.fun(); + } +} + +contract testB { + constructor() public payable { + B b = (new B).value(10)(); + b.fun(); + } +} + + +contract testC { + constructor() public payable{ + C c = (new C).value(10)(); + c.fun(); + } +} + +contract testD { + constructor() public payable{ + D d = (new D).value(10)(); + d.fun(); + } +} + + +contract A { + constructor() public payable{ + selfdestruct(msg.sender); + } + function fun() { + } + +} + +contract B { + constructor() public payable { + revert(); + } + function fun() { + } +} + + +contract C { + constructor() public payable { + assert(1==2); + } + function fun() { + } +} + +contract D { + constructor() public payable { + require(1==2); + } + function fun() { + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/requireExceptiontest1TestRequireContract.sol b/src/test/resources/soliditycode_v0.4.25/requireExceptiontest1TestRequireContract.sol new file mode 100644 index 00000000000..a7c874ebd92 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/requireExceptiontest1TestRequireContract.sol @@ -0,0 +1,15 @@ +pragma solidity ^0.4.0; +contract TestThrowsContract{ + function testAssert(){ + assert(1==2); + } + function testRequire(){ + require(2==1); + } + function testRevert(){ + revert(); + } + function testThrow(){ + throw; + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/requireExceptiontest2TestThrowsContract.sol b/src/test/resources/soliditycode_v0.4.25/requireExceptiontest2TestThrowsContract.sol new file mode 100644 index 00000000000..a7c874ebd92 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/requireExceptiontest2TestThrowsContract.sol @@ -0,0 +1,15 @@ +pragma solidity ^0.4.0; +contract TestThrowsContract{ + function testAssert(){ + assert(1==2); + } + function testRequire(){ + require(2==1); + } + function testRevert(){ + revert(); + } + function testThrow(){ + throw; + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/requireExceptiontest3TestRevertContract.sol b/src/test/resources/soliditycode_v0.4.25/requireExceptiontest3TestRevertContract.sol new file mode 100644 index 00000000000..a7c874ebd92 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/requireExceptiontest3TestRevertContract.sol @@ -0,0 +1,15 @@ +pragma solidity ^0.4.0; +contract TestThrowsContract{ + function testAssert(){ + assert(1==2); + } + function testRequire(){ + require(2==1); + } + function testRevert(){ + revert(); + } + function testThrow(){ + throw; + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/requireExceptiontest4noPayableContract.sol b/src/test/resources/soliditycode_v0.4.25/requireExceptiontest4noPayableContract.sol new file mode 100644 index 00000000000..59c15a1b1ab --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/requireExceptiontest4noPayableContract.sol @@ -0,0 +1,8 @@ +pragma solidity ^0.4.0; + +contract noPayableContract { + +function noPayable() public returns (uint){ +return msg.value; +} +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/requireExceptiontest5noPayableConstructor.sol b/src/test/resources/soliditycode_v0.4.25/requireExceptiontest5noPayableConstructor.sol new file mode 100644 index 00000000000..c1138704b8b --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/requireExceptiontest5noPayableConstructor.sol @@ -0,0 +1,10 @@ +pragma solidity ^0.4.0; + +contract MyContract { + uint money; + + function MyContract(uint _money) { + require(msg.value >= _money); + money = _money; + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/requireExceptiontest6transferTestContract.sol b/src/test/resources/soliditycode_v0.4.25/requireExceptiontest6transferTestContract.sol new file mode 100644 index 00000000000..b0d93d238cf --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/requireExceptiontest6transferTestContract.sol @@ -0,0 +1,8 @@ +pragma solidity ^0.4.0; + +contract transferTestContract { + function tranferTest(address addr) public payable{ + addr.transfer(10); + + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/requireExceptiontest7payableFallbakContract.sol b/src/test/resources/soliditycode_v0.4.25/requireExceptiontest7payableFallbakContract.sol new file mode 100644 index 00000000000..af290a06804 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/requireExceptiontest7payableFallbakContract.sol @@ -0,0 +1,13 @@ +pragma solidity ^0.4.0; + +contract Test { + function() { x = 1; } + uint x; +} + + +contract Caller { + function callTest(Test test) { + test.call(0xabcdef01); // hash does not exist + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/requireExceptiontest8newContractGasNoenough.sol b/src/test/resources/soliditycode_v0.4.25/requireExceptiontest8newContractGasNoenough.sol new file mode 100644 index 00000000000..79066c2bfc8 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/requireExceptiontest8newContractGasNoenough.sol @@ -0,0 +1,18 @@ +pragma solidity ^0.4.0; + +contract Account{ + uint256 public accId; + + function Account(uint accountId) payable{ + accId = accountId; + } +} + +contract Initialize{ + // Account public account = new Account(10); + + function newAccount(){ + Account account = new Account(1); + } + +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/requireExceptiontest9MessageUsedErrorFeed.sol b/src/test/resources/soliditycode_v0.4.25/requireExceptiontest9MessageUsedErrorFeed.sol new file mode 100644 index 00000000000..f6187a6c3d1 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/requireExceptiontest9MessageUsedErrorFeed.sol @@ -0,0 +1,18 @@ +pragma solidity ^0.4.0; + +contract MathedFeed { + + function divideMathed() public returns (uint ret) { + uint x=1; + uint y=0; + return x/y; + } +} + + +contract MathedUseContract { + + function MathedUse(address addr) public returns (uint) { + return MathedFeed(addr).divideMathed(); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/requireExceptiontestFunctionUsedErrorFeed.sol b/src/test/resources/soliditycode_v0.4.25/requireExceptiontestFunctionUsedErrorFeed.sol new file mode 100644 index 00000000000..cc1e8c88306 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/requireExceptiontestFunctionUsedErrorFeed.sol @@ -0,0 +1,17 @@ +pragma solidity ^0.4.0; + +contract MessageFeed { + + function mValue() payable returns (uint ret) { + return msg.value; + } +} + +contract MessageUseContract { + function inputValue() payable returns (uint){ + return msg.value; + } + function messageUse(address addr) payable returns (uint) { + return MessageFeed(addr).mValue.value(1)(); + } +} \ No newline at end of file diff --git a/src/test/resources/soliditycode_v0.4.25/walletTestMutiSign004.sol b/src/test/resources/soliditycode_v0.4.25/walletTestMutiSign004.sol new file mode 100644 index 00000000000..7de52e9f155 --- /dev/null +++ b/src/test/resources/soliditycode_v0.4.25/walletTestMutiSign004.sol @@ -0,0 +1,52 @@ +//pragma solidity ^0.4.0; + +contract timeoutTest { + string public iarray1; + // cpu + function oneCpu() { + require(1==1); + } + + function storage8Char() { + iarray1 = "12345678"; + + } + + function testUseCpu(uint256 a) public returns (uint256){ + uint256 count = 0; + for (uint256 i = 0; i < a; i++) { + count++; + } + return count; + } + + + uint256[] public iarray; + uint public calculatedFibNumber; + mapping(address=>mapping(address=>uint256)) public m; + + function testUseStorage(uint256 a) public returns (uint256){ + uint256 count = 0; + for (uint256 i = 0; i < a; i++) { + count++; + iarray.push(i); + } + return count; + } + + // stack + uint n = 0; + function test() { + n += 1; + test(); + } + + function setFibonacci(uint n) public returns (uint256){ + calculatedFibNumber = fibonacci(n); + return calculatedFibNumber; + } + + function fibonacci(uint n) internal returns (uint) { + return fibonacci(n - 1) + fibonacci(n - 2); + } +} \ No newline at end of file diff --git a/src/test/resources/testng.conf b/src/test/resources/testng.conf index 44ddfceea7c..3566037bfd9 100644 --- a/src/test/resources/testng.conf +++ b/src/test/resources/testng.conf @@ -15,15 +15,22 @@ fullnode = { #"47.94.148.150:50051", #"47.94.9.222:50051", #"39.107.87.203:50051", + #"39.105.89.183:50051", + #"39.107.248.113:50051", + #Replay env + #"47.94.239.172:50051", + #"39.105.89.183:50051", #New beta1 "47.94.197.215:50051", "101.200.52.146:50051", #New beta2 + #"47.94.197.215:50052", #"101.200.52.146:50052", + #MainNet #"54.236.37.243:50051", #"52.53.189.99:50051", @@ -44,22 +51,27 @@ solidityNode = { #"47.94.135.251:50051", #"47.94.9.222:50061", #new beta1 - "47.94.197.215:18895", + #"47.94.197.215:18895", #new beta2 - "101.200.52.146:18895", + #"101.200.52.146:18895", ] } httpnode = { ip.list = [ + #"39.105.89.183:8090", + #"39.107.248.113:8090", + #"39.105.89.183:8091", + # "39.105.89.183:8090", "127.0.0.1:8090", "127.0.0.1:8093", "127.0.0.1:8097", "47.94.197.215:8091", - "101.200.52.146:8091" + "101.200.52.146:8091", + "47.94.197.215:8097", ] } @@ -69,8 +81,10 @@ foundationAccount = { key1 = FC8BF0238748587B9617EB6D15D47A66C0E07C1A1959033CF249C6532DC29FE6 key2 = 6815B367FDDE637E53E9ADC8E69424E07724333C9A2B973CFA469975E20753FC #Main_in_mock_foundationAccount_key - #key1 = 7c4977817417495f4ca0c35ab3d5a25e247355d68f89f593f3fea2ab62c8644f - #key2 = 1fe1d91bbe3ac4ac5dc9866c157ef7615ec248e3fd4f7d2b49b0428da5e046b2 + + #key1 = 324a2052e491e99026442d81df4d2777292840c1b3949e20696c49096c6bacb8 + #key2 = 2925e186bb1e88988855f11ebf20ea3a6e19ed92328b0ffb576122e769d45b68 + } @@ -142,6 +156,11 @@ defaultParameter = { httpSoTimeout = 2000 createWitnessAmount = 9999000000 operations = 7fff1fc0037e0000000000000000000000000000000000000000000000000000 + delayTransactionFee = 100000 + cancleDelayTransactionFee = 50000 + solidityCompilerVersion = "v5" + solidityCompile = "solcDIR/solc" + } @@ -305,10 +324,12 @@ code = { code_ContractTrcToken078_AddressTest4 = "6080604052610264806100136000396000f30060806040526004361061003d5763ffffffff60e060020a600035041663648efe8b811461003f578063b45f578b14610059578063d818452114610073575b005b61003d600160a060020a036004358116906024351661008d565b61003d600160a060020a036004358116906024351661011c565b61003d600160a060020a03600435811690602435166101a9565b81600160a060020a031660405180807f7472616e73666572546f286164647265737329000000000000000000000000008152506013019050604051809103902060e060020a9004826040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a031681526020019150506000604051808303816000875af2505050505050565b81600160a060020a031660405180807f7472616e73666572546f286164647265737329000000000000000000000000008152506013019050604051809103902060e060020a9004826040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050600060405180830381865af4505050505050565b81600160a060020a031660405180807f7472616e73666572546f286164647265737329000000000000000000000000008152506013019050604051809103902060e060020a9004826040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a031681526020019150506000604051808303816000875af15050505050505600a165627a7a7230582068a85b5cb5a41f10a7ba8250baed5adf37129ff04399bccae69e483fc85448a90029" code_ContractTrcToken078_AddressTest5 = "6080604052610166806100136000396000f3006080604052600436106100325763ffffffff60e060020a6000350416630223024e8114610034578063a03fa7e314610055575b005b61003273ffffffffffffffffffffffffffffffffffffffff60043516610076565b61003273ffffffffffffffffffffffffffffffffffffffff600435166100f7565b8073ffffffffffffffffffffffffffffffffffffffff16600560405180807f73657449282900000000000000000000000000000000000000000000000000008152506006019050604051809103902060e060020a9004906040518263ffffffff1660e060020a02815260040160006040518083038185885af1505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff82169060009060059082818181858883f19350505050158015610136573d6000803e3d6000fd5b50505600a165627a7a72305820ede28ac9884104396c5d52bbf3f480cb637f61bc331c2dc561670e6d2700ad630029" code_ContractTrcToken078_AddressTest6 = "6080604052610172806100136000396000f30060806040526004361061004b5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166367e404ce8114610087578063938b5f32146100df575b6040805132815233602082015281517fdaf0d4aa9a5679e832ac921da67b43572b4326ee2565442d3ed255b48cfb5161929181900390910190a1005b34801561009357600080fd5b50d380156100a057600080fd5b50d280156100ad57600080fd5b506100b661010e565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b3480156100eb57600080fd5b50d380156100f857600080fd5b50d2801561010557600080fd5b506100b661012a565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b60005473ffffffffffffffffffffffffffffffffffffffff16815600a165627a7a7230582084426e82a8fde9cefb0ae9f1561ce743354adada27d217c8614c28829eecbcda0029" + code_Scenario015_TRC20_TRON = "6060604052604060405190810160405280600681526020017f54726f6e697800000000000000000000000000000000000000000000000000008152506000908051906020019062000052929190620001b6565b50604060405190810160405280600381526020017f545258000000000000000000000000000000000000000000000000000000000081525060019080519060200190620000a1929190620001b6565b50600660025560006005556000600660006101000a81548160ff0219169083151502179055506000600660016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034156200011257fe5b5b33600660016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555067016345785d8a000060058190555067016345785d8a0000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b62000265565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620001f957805160ff19168380011785556200022a565b828001600101855582156200022a579182015b82811115620002295782518255916020019190600101906200020c565b5b5090506200023991906200023d565b5090565b6200026291905b808211156200025e57600081600090555060010162000244565b5090565b90565b61111480620002756000396000f300606060405236156100ce576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100d057806307da68f514610169578063095ea7b31461017b57806318160ddd146101d257806323b872dd146101f8578063313ce5671461026e57806342966c681461029457806370a08231146102b457806375f12b21146102fe57806395d89b4114610328578063a9059cbb146103c1578063be9a655514610418578063c47f00271461042a578063dd62ed3e14610484575bfe5b34156100d857fe5b6100e06104ed565b604051808060200182810382528381815181526020019150805190602001908083836000831461012f575b80518252602083111561012f5760208201915060208101905060208303925061010b565b505050905090810190601f16801561015b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561017157fe5b61017961058b565b005b341561018357fe5b6101b8600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610603565b604051808215151515815260200191505060405180910390f35b34156101da57fe5b6101e26107cb565b6040518082815260200191505060405180910390f35b341561020057fe5b610254600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506107d1565b604051808215151515815260200191505060405180910390f35b341561027657fe5b61027e610b11565b6040518082815260200191505060405180910390f35b341561029c57fe5b6102b26004808035906020019091905050610b17565b005b34156102bc57fe5b6102e8600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610c3f565b6040518082815260200191505060405180910390f35b341561030657fe5b61030e610c57565b604051808215151515815260200191505060405180910390f35b341561033057fe5b610338610c6a565b6040518080602001828103825283818151815260200191508051906020019080838360008314610387575b80518252602083111561038757602082019150602081019050602083039250610363565b505050905090810190601f1680156103b35780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156103c957fe5b6103fe600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610d08565b604051808215151515815260200191505060405180910390f35b341561042057fe5b610428610f31565b005b341561043257fe5b610482600480803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091905050610fa9565b005b341561048c57fe5b6104d7600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061101e565b6040518082815260200191505060405180910390f35b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156105835780601f1061055857610100808354040283529160200191610583565b820191906000526020600020905b81548152906001019060200180831161056657829003601f168201915b505050505081565b3373ffffffffffffffffffffffffffffffffffffffff16600660019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415156105e457fe5b6001600660006101000a81548160ff0219169083151502179055505b5b565b6000600660009054906101000a900460ff1615151561061e57fe5b3373ffffffffffffffffffffffffffffffffffffffff1660001415151561064157fe5b60008214806106cc57506000600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054145b15156106d85760006000fd5b81600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a3600190505b5b5b92915050565b60055481565b6000600660009054906101000a900460ff161515156107ec57fe5b3373ffffffffffffffffffffffffffffffffffffffff1660001415151561080f57fe5b81600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561085e5760006000fd5b600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205401101515156108ee5760006000fd5b81600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561097a5760006000fd5b81600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190505b5b5b9392505050565b60025481565b80600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610b665760006000fd5b80600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508060036000600073ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555060003373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35b50565b60036020528060005260406000206000915090505481565b600660009054906101000a900460ff1681565b60018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610d005780601f10610cd557610100808354040283529160200191610d00565b820191906000526020600020905b815481529060010190602001808311610ce357829003601f168201915b505050505081565b6000600660009054906101000a900460ff16151515610d2357fe5b3373ffffffffffffffffffffffffffffffffffffffff16600014151515610d4657fe5b81600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610d955760006000fd5b600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020540110151515610e255760006000fd5b81600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190505b5b5b92915050565b3373ffffffffffffffffffffffffffffffffffffffff16600660019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141515610f8a57fe5b6000600660006101000a81548160ff0219169083151502179055505b5b565b3373ffffffffffffffffffffffffffffffffffffffff16600660019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151561100257fe5b8060009080519060200190611018929190611043565b505b5b50565b6004602052816000526040600020602052806000526040600020600091509150505481565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061108457805160ff19168380011785556110b2565b828001600101855582156110b2579182015b828111156110b1578251825591602001919060010190611096565b5b5090506110bf91906110c3565b5090565b6110e591905b808211156110e15760008160009055506001016110c9565b5090565b905600a165627a7a723058204858328431ff0a4e0db74ff432e5805ce4bcf91a1c59650a93bd7c1aec5e0fe10029" } abi = { + abi_Scenario015_TRC20_TRON = "[{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\",\"stateMutability\":\"view\"},{\"constant\":false,\"inputs\":[],\"name\":\"stop\",\"outputs\":[],\"payable\":false,\"type\":\"function\",\"stateMutability\":\"nonpayable\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\",\"stateMutability\":\"nonpayable\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\",\"stateMutability\":\"view\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\",\"stateMutability\":\"nonpayable\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\",\"stateMutability\":\"view\"},{\"constant\":false,\"inputs\":[{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"payable\":false,\"type\":\"function\",\"stateMutability\":\"nonpayable\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\",\"stateMutability\":\"view\"},{\"constant\":true,\"inputs\":[],\"name\":\"stopped\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\",\"stateMutability\":\"view\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\",\"stateMutability\":\"view\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\",\"stateMutability\":\"nonpayable\"},{\"constant\":false,\"inputs\":[],\"name\":\"start\",\"outputs\":[],\"payable\":false,\"type\":\"function\",\"stateMutability\":\"nonpayable\"},{\"constant\":false,\"inputs\":[{\"name\":\"_name\",\"type\":\"string\"}],\"name\":\"setName\",\"outputs\":[],\"payable\":false,\"type\":\"function\",\"stateMutability\":\"nonpayable\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\",\"stateMutability\":\"view\"},{\"inputs\":[],\"payable\":false,\"type\":\"constructor\",\"stateMutability\":\"nonpayable\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_spender\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"}]" abi_AssertException_testdivideInt = "[{\"constant\":false,\"inputs\":[{\"name\":\"x\",\"type\":\"int256\"},{\"name\":\"y\",\"type\":\"int256\"}],\"name\":\"divideIHaveArgsReturn\",\"outputs\":[{\"name\":\"z\",\"type\":\"int256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" abi_AssertException_testfindArgsContractMinTest = "[{\"constant\":false,\"inputs\":[{\"name\":\"i\",\"type\":\"uint256\"}],\"name\":\"findArgsByIndexTest\",\"outputs\":[{\"name\":\"z\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" abi_AssertException_testbyteMinContract = "[{\"constant\":false,\"inputs\":[{\"name\":\"i\",\"type\":\"uint256\"}],\"name\":\"testBytesGet\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes1\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"