From 5298f4348f824df26aa54d8e9f4d8bc243f5ee15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=BF=97=E5=90=8C?= Date: Thu, 30 Aug 2018 11:22:07 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=A1=B9=E7=9B=AE=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitattributes | 63 ++++ .gitignore | 261 +++++++++++++++ NeoContract.sln | 37 +++ NeoContract/Neo.ConvertTask.dll | Bin 0 -> 6144 bytes NeoContract/Neo.SmartContract.Framework.dll | Bin 0 -> 18432 bytes NeoContract/Properties/AssemblyInfo.cs | 36 ++ NeoContract/SGAS.cs | 350 ++++++++++++++++++++ NeoContract/SGAS.csproj | 67 ++++ NeoContract/TransferInfo.cs | 11 + NeoContract/build.tasks | 4 + SGAS.UnitTests/App.config | 86 +++++ SGAS.UnitTests/Program.cs | 32 ++ SGAS.UnitTests/Properties/AssemblyInfo.cs | 36 ++ SGAS.UnitTests/SGAS.UnitTests.csproj | 243 ++++++++++++++ SGAS.UnitTests/SGASTest.cs | 312 +++++++++++++++++ SGAS.UnitTests/packages.config | 77 +++++ Tools/App.config | 6 + Tools/Program.cs | 65 ++++ Tools/Properties/AssemblyInfo.cs | 36 ++ Tools/Tools.csproj | 237 +++++++++++++ Tools/packages.config | 76 +++++ readme.md | 45 +++ 22 files changed, 2080 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 NeoContract.sln create mode 100644 NeoContract/Neo.ConvertTask.dll create mode 100644 NeoContract/Neo.SmartContract.Framework.dll create mode 100644 NeoContract/Properties/AssemblyInfo.cs create mode 100644 NeoContract/SGAS.cs create mode 100644 NeoContract/SGAS.csproj create mode 100644 NeoContract/TransferInfo.cs create mode 100644 NeoContract/build.tasks create mode 100644 SGAS.UnitTests/App.config create mode 100644 SGAS.UnitTests/Program.cs create mode 100644 SGAS.UnitTests/Properties/AssemblyInfo.cs create mode 100644 SGAS.UnitTests/SGAS.UnitTests.csproj create mode 100644 SGAS.UnitTests/SGASTest.cs create mode 100644 SGAS.UnitTests/packages.config create mode 100644 Tools/App.config create mode 100644 Tools/Program.cs create mode 100644 Tools/Properties/AssemblyInfo.cs create mode 100644 Tools/Tools.csproj create mode 100644 Tools/packages.config create mode 100644 readme.md diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..48a07ae --- /dev/null +++ b/.gitignore @@ -0,0 +1,261 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +project.fragment.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +#*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc diff --git a/NeoContract.sln b/NeoContract.sln new file mode 100644 index 0000000..ab8795c --- /dev/null +++ b/NeoContract.sln @@ -0,0 +1,37 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27703.2035 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SGAS", "NeoContract\SGAS.csproj", "{15DFB6B6-A57D-4A26-A5B7-EA1B2D102E20}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tools", "Tools\Tools.csproj", "{A4F2D281-A2E9-4950-AA18-098BF614FD6C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SGAS.UnitTests", "SGAS.UnitTests\SGAS.UnitTests.csproj", "{5C287CB0-FC56-482A-8C91-DB83B60C9B70}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {15DFB6B6-A57D-4A26-A5B7-EA1B2D102E20}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {15DFB6B6-A57D-4A26-A5B7-EA1B2D102E20}.Debug|Any CPU.Build.0 = Debug|Any CPU + {15DFB6B6-A57D-4A26-A5B7-EA1B2D102E20}.Release|Any CPU.ActiveCfg = Release|Any CPU + {15DFB6B6-A57D-4A26-A5B7-EA1B2D102E20}.Release|Any CPU.Build.0 = Release|Any CPU + {A4F2D281-A2E9-4950-AA18-098BF614FD6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A4F2D281-A2E9-4950-AA18-098BF614FD6C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A4F2D281-A2E9-4950-AA18-098BF614FD6C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A4F2D281-A2E9-4950-AA18-098BF614FD6C}.Release|Any CPU.Build.0 = Release|Any CPU + {5C287CB0-FC56-482A-8C91-DB83B60C9B70}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5C287CB0-FC56-482A-8C91-DB83B60C9B70}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5C287CB0-FC56-482A-8C91-DB83B60C9B70}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5C287CB0-FC56-482A-8C91-DB83B60C9B70}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {CFA1CA3D-396C-4D4F-B1BC-E7B18DC9A5FB} + EndGlobalSection +EndGlobal diff --git a/NeoContract/Neo.ConvertTask.dll b/NeoContract/Neo.ConvertTask.dll new file mode 100644 index 0000000000000000000000000000000000000000..2de7c659fbdd1841938844ff83b0eb5a2cb7f5af GIT binary patch literal 6144 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 literal 0 HcmV?d00001 diff --git a/NeoContract/Neo.SmartContract.Framework.dll b/NeoContract/Neo.SmartContract.Framework.dll new file mode 100644 index 0000000000000000000000000000000000000000..66491b776aff65d6347e3f39a6fb4b866e6d902c GIT binary patch literal 18432 zcmeHvd3YSvmG8OLUA;?|h_8psU?-Awp-mzcgrg# z0)w0oAWq^4$UsJ68{h*T%p(ceMaIL<49pOQFnmM|WRmbD!81e10t53qr>d)4l7R{D zy+7W3DY<@iwtMcq=Pq^YR<)bAA0-D7IdOjQ0nsD4@=+uB(J%yc@q+IZ)5G3p7e1nz zo?RH}k7a_Xbh0lU9SHVB6NzLt*lh&UgNa})5v*$s2M3b9MpaRfZ?WaNt)8e!IcVCJ z!_Vh(8>iEPezk(=LP$KO^xO_ygE+fz5|s$8ndN2ymtT%iAmn^FsOB0r<$w9B#j*&; z&n_iuWul8{o$Z7L)-gmB0QtmrqDW5m-?;|uqKmZ$d_zIHs;sdu3%=%j0CZAUtK8t^ z2%=O~=}fu@oRqB#gbQa4&Vr)`lB%>3Pr{JPN<%o=*9M#gM-9>X0#?X599JA%HjQ+; z91YX7hDeF@Plr>rg9)@o<@6OAtweJ8Db*^b6Zy~{Gu~G|*D_aT2G|3R8)6F}nDxH$ zyCIv&GR<*FQWH&Ip%cdk)%dXV$yrFUpkj&(k(Xb3{i(=Z+|3Fs4QdrAiOb{gly5Ij z&PKu@yRIk)b&F^A)_}(}xFPnwv&g&r`O4F*LRX?fX|B-vTrE&W5kQfdtPlZ`&VgIv zq^QEgq$02_3W?3!ww$k-*d{m@4uTN8d|29XmQ%Vk_UXaMl0Y`J$0s{-xxu zlrpdWxU^IAwjFS6mVaE?x#qb#J1bIBX({)goc6N+gS6;12)30kkByIPrzv&L7o6+- zNz&&E|4GxE6+p*4EH$xv=qDpE8HGQ!URg5@&s%#|SFNa8wPIEEIbhJ6;=t$T5-qxd z==@WN78ijIXVbAn9|jsG#|nudE!q^OUeG+vFWR`Nu@2WP_?OszeLUIC#yBwG)s_Xf zDK7#~e^jezmO0NY02{=Kkww?z9L9+*BV!JArrU9%Z&Mjg?&m9T^8ASLXx(?Vdzj}z zf2V$f&qX~h#!@%qV*Q|RI(-lGpNn?s{caci-nGT+qIY%1TZBGK@DY*xSn#k&!a_gd zdC23UE=#SBrvvl9*etHBDewhT>#4)$mRNpcCOkyR8AKFH!8-E(02${3T_p=UhrJO z)q3cL{z$BtwELMN%dBp5S*y{#&7!NG{(O^avgojEeT}#WF1P1%he8l;BH(uL=H8 zEC&QhaE8bi2(A%)Lgc-II|RQW_!q#1)anQ+?vwTCSIXZ2{HePE@&yjYwGOsf;NX@2 zO@UV6bAcwY=RWN8hJhDqjHN<1fo=<8a-m_*ZSJj@p0=7?x#8OZ?k1Zn;aOge5&E6C z2cC1>tASmLCw@Lg=+(ewisy7bM(8T{UWFU393%8~{~_hJIpx1h$@B=x2%T^YD@^5b zjL^>Ok4LN zxN|Mtw;ZpiIkeu^y#~%aj!_f+T;X;s$1!>a9B#@MR|0OH&HW>|`8Idh`5T4BxE#mm zu=5=iG#NTZFZoDYL}5EWMN6o|D$8DnPg_F0wyp#^^BD0g^c8ET+uY;s=>^TxQr-B=_^HX$&mBX;d=h&+9T)T6zmgii7iURIkMX;pMZLCJU>!pAWE+`n8_B_?-=pJA@md z=e-ZX@)?VJ+4*g)iJYf#{v-6V^HHsZ>MZU_{}Wmp4cXlDT04zdTub05T7=%Sx!1KV zv~H2X4Nsyh2G6h_(V^0A$;MiZl?QvXgb1yruaD1kK z8+Kf2bGseaI}R6cw>Yk$x`Id?q2>vkX*%rTK6u1RH|)6pbBN8+fB5ckJ9m_kgdEn=QJ{C(Z9wM?nsr*EG((^Q4wM0_@y9j|9Gp{Q6I7$@5^|@;rA%z7BF{ zK0=pGN~h#uDu)j`_z7bwHsAqJqm*c$0d3l7^cZLe3nY0Os{nt_GUu}xw_`<&8r8dV zv?)<^RQ&%)@I8&SQ}N4APU{yxzksDiEOA(pLapg-mUxRxs@Y;$iqbmiU-1;A(?vdh z?)wMOZrTD`(OM}p*Gtj3&TadL>e6bPmu#UC7Hx&m(u8IA0gNC%JqY zxp*i7+Dl)=!bQ<1OEoHa{gagQpW#Q7s4Du?XouAb`BeY6CGSfKUqA#DaeFB;OK$dr zlhe5}`5@a5a`36o#89N z(=201uuf}aD_??g5@cPm26`k$h3`CxWjD{*o4ZmeVik^X_W; zH@elimL3whj$XDEeJ>zbLfb*lpblU;eHu8Ax`07EC+m1p?*&%SPT(@Z71$ZjX*KNv zuES1`PUmBHL8lr@0qZCYY`_!0j#cL#U>ofNM(6-=E1r{eGT492lx_f zb$W$<031gOo!+1y0e^vXI{k_s1D-%?o!+LWfWL`{{pN~ZvdC6e+8~kzW}aQZvxk;UjffozX8^$6Tmw4 z@4yE2Hn2&(18h^j2S(H%fm_vkzz+33unU_-h`-W+{mKc9D;F@OJix5-0r#l@@N!iQ z98x8~t5q5BvuXzLIyDP;RFwmdsky+L)I8uV>QvyU3Igv?rvdL)i-Gs4(}54F3gE-4 zQh8`hEdw4`)sT#<0E=cj|c2koX)zyH=~iLXTR=k};vjL_03@ zxX`cD=jquZQd}NFo6XZ5ioFFz5>!voX?l&&HP9~AYem~7k}gQ9^&XK7iDXD|UZX;f zBJEoJcF~TBWDGH?(Z_`z2Ysnd+RL<04+5{yYk*hlUBGMgA>dJc6gZ;au5sDMK;NR1 zgQHg?IOKSlZqrABck5%o2lR2^!|0MP(|7bBa7?cOKBf;jIn|i6Qaz)O1K-t2uT)j8 zAh6R_1H8f21-#!i1bo~z27KK$4*X9S-e;&e?jUfby9U_e?gH*|4*{=oj{?8y9s~Yw z_c-uLchFs_UUk<1m8T0B^o#;8^o#*JJmZ4osZ<9%LBSf}jh-&xcRWMDpLj-r?|R07 z<=%1NIxl%ERm2+vro1)4W8N;{{oWzqDOrFzUa1boXk3Uv9$fb;xs1ilQP zR8*-}`-8wXe+@9^?*bn24*~zuKMH)It(jPuJ?!Y+kngEql zsyhNf;PF5W@aKUcV4!FeSWz?%tSzF_O0~VH2AD4D0$yJ<1iY(gA@+MO#3*gRN=RXC zrI8OK-j7vK5x8R9o2KE;R03)`w)tn^zBvnb&DnGs?oNxrosRp{8Mw=yiM#Al++~+z zUH)7553znY;yDhy#s4(0#Lw%i&pG}H_+7^%FkR&QPv8{+-m01|+P6I}(9?vTCpNEp zSuz%2{Eg-VUhC(yriVWUiXpkkJss%rl>>v$Q-NO$oCY*~UMi*f7YCQ*cN(WP{eLfT z25iidU*zV}a*Z@Z*ntR_BEkx9K`?)mtyYKs0z{7uye5hxB_j%?;sZeSJD#TDx}u1J~$J2Hd1J`5pATQz0U$R z!d9aeSZR2Be>Sj<)&eiVYDlAY%;6e^v9qsX#c&aD6V^u>RwA`PgX)1h;ZMVgp%ECv zJg?CJH3Kh)KaCE-lZI777D9e6x93zb#T9hFO2qS-g+CYd` zO>G<6Tbn~ok#L0hNUKe@HG>qK1`cKO`Gb& zbaDN*Fx7@4oEcJWs*NCk5o)U65J5z#y>VkhL?Q@T#0(;8OOb~5)-8=2m~6+{*n)CI zsIGCdsiEf3R`w{3zUn=&jOFfwv&k0!uHqPtBWp*_)9JlY*M zxyDRebiZ(k=zuAT#6YwUCbE33-)Hm;a$DCY`eF&oV1Ek!(y_iiBOPIy^OQIWmo~D4 z=|pFiHD*+W4DZimje)A#WZE!0(f)9(FA;?;s%TSf(R9Y3+O!ePB9CO95jXmnY>wf> zFkI`5?m^CXeLA@}!{rWVS)37MYcRFRfmAGRq&FG~o_mbmP!@0gy9c2%1DNM+Ni0&iDe5@M51YgW&^%xGxjFay9?}7sh(&&o);iE69x7Avgoyl zd)_9O$p+L7qwwU)#>CEKdO${JH2$Gh=zu$8eS-+jgd8I2Xd)BsnJCOld1jaVEqNEmSn;hh)or2 ziDmn(0hRZIZWJ8|rPI;%2IdnAWz0`eC_LDmk&jZSDcL99c^VNSKdT5^ zi|&G?lcd(@oFI=RCmSWQ>HP(=j6Gk8=eD%5M{+ggo&C8IG#QD$Y`@Gz_&#tq@$Do$ z5KU(h?Q9y|q{{BuWDH!4Dg{ba{^%$8dGmuoD7#tvc zlhd=ir#~7?h__Jh0H~-S&qAn7PmD(frEH4jR`6+$Ic_H0#R_j?WHs7GeEP#JDjk;^ z6MK^89j{=7a9|4ATyq;c4HGq?=%TqX}#DNqSvcZV<8fkR8^|3y_!C>|@jm#OG8qL1Jt%|T(%9F`j z_p&xA*kHs{mT6-qGYB$fUZR7zd#0(X2lt~~G+PjcbgUM8ZKdPY5~PN;t~A5Zxi6q~lCnoD=MN<9wOd|ktb)UMLS znyc91D(iQ;N{5D=L7J~~1Q8lir90#@UoYK(Era=bF|ZiXA_*E34vC%zn+QT6O<5EU z*mxdr9?}QZbbJWo4r;*ZN=F9MNf5Nsm{!mrVdaed z3T-}A^K~>XZ@VxIuSa1-GSW-mJ}m@i6H`vueXPWP#;7J zsOHae0wqNKW^Vnt-1^Pjz+1V2vT_4u=GLFft-sjHt-si;1Wcq7;7OZV)*&rZ25G=# zkr4Ie1}V!5Vy_zX<%ovcS%J24RY=d!L8BKiD#+3P0FR>r&FbN1^>DL7i$GTppFW%# zjLP~!cyao{p!NWzd${%v4|zE;8@TaJFSc=ToQlCs5pC9%bTowptbNaq^z-uzUUZO~ z2MKLdG`FgyK4Pz^mRT#73;4@sxG0`stLkEzR6M%B1#@u;rwQ7c;OZHQrbYUVAXW%L zEUx7?L3mrI%X5>IXU@tM)oYdm)&{3o1{Iz15lb?>Oh+6G{tij&1C1fTRm>^)~XpVoM?8Ts&E<2ZXOqBeOs|&6Vd=xw-tGS^#TFN;C0&cHWV- ztAJOXG%YVRml<@LqWLV82Mn%y!J@`oJlP>XnF&4=ny;w*!#qsV$^#5%VlCMwrY+FQ z%H19w`G+4)D;!NMxSh11^ya9yOJaXZi3D$P>q89&65~R ze8|9?d|Jd&J?S%TVbjdQcOznGZQxhQ65bwCxqbaAUR2v7)0UdMBzAmqbH0o#**MI% zU7?P*9PPo7Q%rcuva`x*t;M@Ns&jJQQL*#4o;tXG-0sqMa??P8j%+VEAwS;OS>}Y+ zKBFCroLshh?UpSVg89CbyVFflniFYm4w|I2A1E=&eCf4(%Jr*aaa}S;NWHCu! z@Pv&IK4<~A`y`VI&&GCK?V@oF&249UxJ=N=?mO9iiXVsbLCFm~sRfIz-kuwHX7O2J z-;Z+loV?2Fak){KSD15+IVQ0}8RrEGc@;Tj2TC{^eP`*9Nj0}=U~j`Y?^2u>m^wyY z!A!?_2F@Qq_k#i*M0i^~@n{d%g%53A`Nqv1m()GD_KbDkyyUJwu#ehvJ2qvo2i4Kj zZzK+M)FpdlhbYrg&F>aE5=L@4egnQsp-Tne_cG@%-eMGw#6`H1JFwM!4kNc9I~lC|1A0cC<6RTILzt9Oa8)xAAsa{ zk3)r0b3~cH9pBo8FB|eNz(Mn`0yg6fdM6NXUO_eD-Fgf7M&JhXSNHh!;#=>tA3Vmw z-eF%avNCew%9_HX4vd1=D83ThfVcN?ywm63Cho*<3Hewo@7^QOMj_2WAH|n|F=+9# zVL2Xjp3l$NC{q?zG06K);;CG0R^aOd^KUi2Aixt7zBSLAZR!}Urb&wRZn&fwK zYvtPt|EGksYY1(bLA?ghyW@yr5F=}13+L0A?TZln`S_m_fj0C13_1V&|0xyvb3Oi) G2>cftx}0qQ literal 0 HcmV?d00001 diff --git a/NeoContract/Properties/AssemblyInfo.cs b/NeoContract/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..d7e9af2 --- /dev/null +++ b/NeoContract/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("NeoContract5")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("NeoContract5")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("15dfb6b6-a57d-4a26-a5b7-ea1b2d102e20")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/NeoContract/SGAS.cs b/NeoContract/SGAS.cs new file mode 100644 index 0000000..8b41715 --- /dev/null +++ b/NeoContract/SGAS.cs @@ -0,0 +1,350 @@ +using Neo.SmartContract.Framework; +using Neo.SmartContract.Framework.Services.Neo; +using Neo.SmartContract.Framework.Services.System; +using Helper = Neo.SmartContract.Framework.Helper; +using System.ComponentModel; +using System.Numerics; +using System; + +namespace SGAS +{ + public class SGAS : SmartContract + { + [DisplayName("transfer")] + public static event deleTransfer Transferred; + public delegate void deleTransfer(byte[] from, byte[] to, BigInteger value); + + [DisplayName("refund")] + public static event deleRefundTarget Refunded; + public delegate void deleRefundTarget(byte[] txid, byte[] who); + + private static readonly byte[] AssetId = Helper.HexToBytes("e72d286979ee6cb1b7e65dfddfb2e384100b8d148e7758de42e4168b71792c60"); //GAS ID, littleEndian + + //StorageMap contract, key: "totalSupply" + //StorageMap refund, key: txHash + //StorageMap asset, key: account + //StorageMap txInfo, key: txHash + + public static object Main(string method, object[] args) + { + if (Runtime.Trigger == TriggerType.Verification) + { + var tx = ExecutionEngine.ScriptContainer as Transaction; + var inputs = tx.GetInputs(); + var outputs = tx.GetOutputs(); + //Check if the input has been marked + foreach (var input in inputs) + { + if (input.PrevIndex == 0)//If UTXO n is 0, it is possible to be a marker UTXO + { + StorageMap refund = Storage.CurrentContext.CreateMap(nameof(refund)); + var refundMan = refund.Get(input.PrevHash); //0.1 + //If the input that is marked for refund + if (refundMan.Length > 0) + { + //Only one input and one output is allowed in refund + if (inputs.Length != 1 || outputs.Length != 1) + return false; + return outputs[0].ScriptHash.AsBigInteger() == refundMan.AsBigInteger(); + } + } + } + var currentHash = ExecutionEngine.ExecutingScriptHash; + //If all the inputs are not marked for refund + BigInteger inputAmount = 0; + foreach (var refe in tx.GetReferences()) + { + if (refe.AssetId.AsBigInteger() != AssetId.AsBigInteger()) + return false;//Not allowed to operate assets other than GAS + + if (refe.ScriptHash.AsBigInteger() == currentHash.AsBigInteger()) + inputAmount += refe.Value; + } + //Check that there is no money left this contract + BigInteger outputAmount = 0; + foreach (var output in outputs) + { + if (output.ScriptHash.AsBigInteger() == currentHash.AsBigInteger()) + outputAmount += output.Value; + } + return outputAmount == inputAmount; + } + else if (Runtime.Trigger == TriggerType.Application) + { + var callscript = ExecutionEngine.CallingScriptHash; + + if (method == "balanceOf") return BalanceOf((byte[])args[0]); + + if (method == "decimals") return Decimals(); + + if (method == "getRefundTarget") return GetRefundTarget((byte[])args[0]); + + if (method == "getTxInfo") return GetTxInfo((byte[])args[0]); + + if (method == "mintTokens") return MintTokens(); + + if (method == "name") return Name(); + + if (method == "refund") return Refund((byte[])args[0]); + + if (method == "symbol") return Symbol(); + + if (method == "supportedStandards") return SupportedStandards(); + + if (method == "totalSupply") return TotalSupply(); + + if (method == "transfer") return Transfer((byte[])args[0], (byte[])args[1], (BigInteger)args[2], callscript); + + if (method == "transferAPP") return TransferAPP((byte[])args[0], (byte[])args[1], (BigInteger)args[2], callscript); + } + else if (Runtime.Trigger == TriggerType.VerificationR) //Backward compatibility, refusing to accept other assets + { + var currentHash = ExecutionEngine.ExecutingScriptHash; + var tx = ExecutionEngine.ScriptContainer as Transaction; + foreach (var output in tx.GetOutputs()) + { + if (output.ScriptHash == currentHash && output.AssetId.AsBigInteger() != AssetId.AsBigInteger()) + return false; + } + return true; + } + return false; + } + + [DisplayName("balanceOf")] + public static BigInteger BalanceOf(byte[] account) + { + if (account.Length != 20) + throw new InvalidOperationException("The parameter account SHOULD be 20-byte addresses."); + StorageMap asset = Storage.CurrentContext.CreateMap(nameof(asset)); + return asset.Get(account).AsBigInteger(); //0.1 + } + [DisplayName("decimals")] + public static byte Decimals() => 8; + + [DisplayName("getRefundTarget")] + public static byte[] GetRefundTarget(byte[] txId) + { + if (txId.Length != 32) + throw new InvalidOperationException("The parameter txId SHOULD be 32-byte transaction hash."); + StorageMap refund = Storage.CurrentContext.CreateMap(nameof(refund)); + return refund.Get(txId); //0.1 + } + + [DisplayName("getTxInfo")] + public static TransferInfo GetTxInfo(byte[] txId) + { + if (txId.Length != 32) + throw new InvalidOperationException("The parameter txId SHOULD be 32-byte transaction hash."); + StorageMap txInfo = Storage.CurrentContext.CreateMap(nameof(txInfo)); + var result = txInfo.Get(txId); //0.1 + if (result.Length == 0) return null; + return Helper.Deserialize(result) as TransferInfo; + } + + private static bool IsPayable(byte[] to) + { + var c = Blockchain.GetContract(to); //0.1 + return c == null || c.IsPayable; + } + + /// + /// Global Asset -> NEP5 Asset + /// + [DisplayName("mintTokens")] + public static bool MintTokens() + { + var tx = ExecutionEngine.ScriptContainer as Transaction; + + //Person who sends a global asset, receives a NEP5 asset + byte[] sender = null; + var inputs = tx.GetReferences(); + foreach (var input in inputs) + { + if (input.AssetId.AsBigInteger() == AssetId.AsBigInteger()) + sender = sender ?? input.ScriptHash; + //SGAS address as inputs is not allowed + if (input.ScriptHash.AsBigInteger() == ExecutionEngine.ExecutingScriptHash.AsBigInteger()) + return false; + } + if (GetTxInfo(tx.Hash) != null) + return false; + + //Amount of exchange + var outputs = tx.GetOutputs(); + ulong value = 0; + foreach (var output in outputs) + { + if (output.ScriptHash == ExecutionEngine.ExecutingScriptHash && + output.AssetId.AsBigInteger() == AssetId.AsBigInteger()) + { + value += (ulong)output.Value; + } + } + + //Increase the total amount of contract assets + StorageMap contract = Storage.CurrentContext.CreateMap(nameof(contract)); + var totalSupply = contract.Get("totalSupply").AsBigInteger(); //0.1 + totalSupply += value; + contract.Put("totalSupply", totalSupply); //1 + + //Issue NEP-5 asset + StorageMap asset = Storage.CurrentContext.CreateMap(nameof(asset)); + var amount = asset.Get(sender).AsBigInteger(); //0.1 + asset.Put(sender, amount + value); //1 + + SetTxInfo(null, sender, value); + Transferred(null, sender, value); + return true; + } + + [DisplayName("name")] + public static string Name() => "NEP5 GAS"; + + /// + /// NEP5 Asset -> Global Asset + /// In the pre-refund phase you need to build a TX (SC -> SC) whose Input is a UTXO of the contract. + /// + [DisplayName("refund")] + public static bool Refund(byte[] from) + { + if (from.Length != 20) + throw new InvalidOperationException("The parameter from SHOULD be 20-byte addresses."); + var tx = ExecutionEngine.ScriptContainer as Transaction; + //output[0] Is the asset that the user want to refund + var preRefund = tx.GetOutputs()[0]; + //refund assets wrong, failed + if (preRefund.AssetId.AsBigInteger() != AssetId.AsBigInteger()) return false; + + //Not to itself, failed + if (preRefund.ScriptHash.AsBigInteger() != ExecutionEngine.ExecutingScriptHash.AsBigInteger()) return false; + + //double refund + StorageMap refund = Storage.CurrentContext.CreateMap(nameof(refund)); + if (refund.Get(tx.Hash).Length > 0) return false; //0.1 + + if (!Runtime.CheckWitness(from)) return false; //0.2 + + //Reduce the balance of the refund person + StorageMap asset = Storage.CurrentContext.CreateMap(nameof(asset)); + var fromAmount = asset.Get(from).AsBigInteger(); //0.1 + var preRefundValue = preRefund.Value; + if (fromAmount < preRefundValue) + return false; + else if (fromAmount == preRefundValue) + asset.Delete(from); //0.1 + else + asset.Put(from, fromAmount - preRefundValue); //1 + refund.Put(tx.Hash, from); //1 + + //Change the totalSupply + StorageMap contract = Storage.CurrentContext.CreateMap(nameof(contract)); + var totalSupply = contract.Get("totalSupply").AsBigInteger(); //0.1 + totalSupply -= preRefundValue; + contract.Put("totalSupply", totalSupply); //1 + + SetTxInfo(from, null, preRefundValue); + Transferred(from, null, preRefundValue); + Refunded(tx.Hash, from); + return true; + } + + private static void SetTxInfo(byte[] from, byte[] to, BigInteger value) + { + var txid = (ExecutionEngine.ScriptContainer as Transaction).Hash; + TransferInfo info = new TransferInfo + { + from = from, + to = to, + value = value + }; + StorageMap txInfo = Storage.CurrentContext.CreateMap(nameof(txInfo)); + txInfo.Put(txid, Helper.Serialize(info)); //1 + } + + [DisplayName("symbol")] + public static string Symbol() => "SGAS"; + + [DisplayName("supportedStandards")] + public static object SupportedStandards() => "{\"NEP-5\", \"NEP-7\", \"NEP-10\"}"; + + [DisplayName("totalSupply")] + public static BigInteger TotalSupply() + { + StorageMap contract = Storage.CurrentContext.CreateMap(nameof(contract)); + return contract.Get("totalSupply").AsBigInteger(); //0.1 + } +#if DEBUG + [DisplayName("transfer")] //Only for ABI file + public static bool Transfer(byte[] from, byte[] to, BigInteger amount) => true; +#endif + //Methods of actual execution + private static bool Transfer(byte[] from, byte[] to, BigInteger amount, byte[] callscript) + { + //Check parameters + if (from.Length != 20 || to.Length != 20) + throw new InvalidOperationException("The parameters from and to SHOULD be 20-byte addresses."); + if (amount <= 0) + throw new InvalidOperationException("The parameter amount MUST be greater than 0."); + if (ExecutionEngine.EntryScriptHash.AsBigInteger() != callscript.AsBigInteger()) + return false; + if (!IsPayable(to) || !Runtime.CheckWitness(from)/*0.2*/) + return false; + StorageMap asset = Storage.CurrentContext.CreateMap(nameof(asset)); + var fromAmount = asset.Get(from).AsBigInteger(); //0.1 + if (fromAmount < amount) + return false; + if (from == to) + return true; + + //Reduce payer balances + if (fromAmount == amount) + asset.Delete(from); //0.1 + else + asset.Put(from, fromAmount - amount); //1 + + //Increase the payee balance + var toAmount = asset.Get(to).AsBigInteger(); //0.1 + asset.Put(to, toAmount + amount); //1 + + SetTxInfo(from, to, amount); + Transferred(from, to, amount); + return true; + } +#if DEBUG + [DisplayName("transferAPP")] //Only for ABI file + public static bool TransferAPP(byte[] from, byte[] to, BigInteger amount) => true; +#endif + //Methods of actual execution + private static bool TransferAPP(byte[] from, byte[] to, BigInteger amount, byte[] callscript) + { + //Check parameters + if (from.Length != 20 || to.Length != 20) + throw new InvalidOperationException("The parameters from and to SHOULD be 20-byte addresses."); + if (amount <= 0) + throw new InvalidOperationException("The parameter amount MUST be greater than 0."); + if (!IsPayable(to) || from.AsBigInteger() != callscript.AsBigInteger()) + return false; + StorageMap asset = Storage.CurrentContext.CreateMap(nameof(asset)); + var fromAmount = asset.Get(from).AsBigInteger(); //0.1 + if (fromAmount < amount) + return false; + if (from == to) + return true; + + //Reduce payer balances + if (fromAmount == amount) + asset.Delete(from); //0.1 + else + asset.Put(from, fromAmount - amount); //1 + + //Increase the payee balance + var toAmount = asset.Get(to).AsBigInteger(); //0.1 + asset.Put(to, toAmount + amount); //1 + + SetTxInfo(from, to, amount); + Transferred(from, to, amount); + return true; + } + } +} \ No newline at end of file diff --git a/NeoContract/SGAS.csproj b/NeoContract/SGAS.csproj new file mode 100644 index 0000000..afce986 --- /dev/null +++ b/NeoContract/SGAS.csproj @@ -0,0 +1,67 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {15DFB6B6-A57D-4A26-A5B7-EA1B2D102E20} + Library + Properties + SGAS + SGAS + v4.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + none + true + bin\Release\ + + + prompt + 4 + + + + False + .\Neo.SmartContract.Framework.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/NeoContract/TransferInfo.cs b/NeoContract/TransferInfo.cs new file mode 100644 index 0000000..81764ee --- /dev/null +++ b/NeoContract/TransferInfo.cs @@ -0,0 +1,11 @@ +using System.Numerics; + +namespace SGAS +{ + public class TransferInfo + { + public byte[] from; + public byte[] to; + public BigInteger value; + } +} diff --git a/NeoContract/build.tasks b/NeoContract/build.tasks new file mode 100644 index 0000000..87cd344 --- /dev/null +++ b/NeoContract/build.tasks @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/SGAS.UnitTests/App.config b/SGAS.UnitTests/App.config new file mode 100644 index 0000000..8362bcf --- /dev/null +++ b/SGAS.UnitTests/App.config @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SGAS.UnitTests/Program.cs b/SGAS.UnitTests/Program.cs new file mode 100644 index 0000000..c1f0881 --- /dev/null +++ b/SGAS.UnitTests/Program.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Numerics; +using Neo; +using Neo.Core; +using Neo.Implementations.Blockchains.LevelDB; +using Neo.IO; +using Neo.SmartContract; +using Neo.VM; +using Neo.Wallets; +using VMArray = Neo.VM.Types.Array; + +namespace NeoContract.UnitTests +{ + class Program + { + static void Main(string[] args) + { + //Need libleveldb.dll, and requires a platform(x86 or x64) that is consistent with the program. + //Path of blockchain folder + Blockchain.RegisterBlockchain(new LevelDBBlockchain("C:\\Users\\chenz\\Desktop\\PrivateNet\\neo-gui 2.7.6\\Chain_0001142D")); + + SGASTest.MintTokens(); + //SGASTest.Refund(); + //SGASTest.Verify(); + + Console.ReadLine(); + } + } +} diff --git a/SGAS.UnitTests/Properties/AssemblyInfo.cs b/SGAS.UnitTests/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..1372e16 --- /dev/null +++ b/SGAS.UnitTests/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("ConsoleApp2")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ConsoleApp2")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("5c287cb0-fc56-482a-8c91-db83b60c9b70")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +// 方法是按如下所示使用“*”: : +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/SGAS.UnitTests/SGAS.UnitTests.csproj b/SGAS.UnitTests/SGAS.UnitTests.csproj new file mode 100644 index 0000000..a382cbd --- /dev/null +++ b/SGAS.UnitTests/SGAS.UnitTests.csproj @@ -0,0 +1,243 @@ + + + + + Debug + AnyCPU + {5C287CB0-FC56-482A-8C91-DB83B60C9B70} + Exe + SGAS.UnitTests + SGAS.UnitTests + v4.7.1 + 512 + true + + + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\Microsoft.AspNetCore.Hosting.2.0.3\lib\netstandard2.0\Microsoft.AspNetCore.Hosting.dll + + + ..\packages\Microsoft.AspNetCore.Hosting.Abstractions.2.0.3\lib\netstandard2.0\Microsoft.AspNetCore.Hosting.Abstractions.dll + + + ..\packages\Microsoft.AspNetCore.Hosting.Server.Abstractions.2.0.3\lib\netstandard2.0\Microsoft.AspNetCore.Hosting.Server.Abstractions.dll + + + ..\packages\Microsoft.AspNetCore.Http.2.0.3\lib\netstandard2.0\Microsoft.AspNetCore.Http.dll + + + ..\packages\Microsoft.AspNetCore.Http.Abstractions.2.0.3\lib\netstandard2.0\Microsoft.AspNetCore.Http.Abstractions.dll + + + ..\packages\Microsoft.AspNetCore.Http.Extensions.2.0.3\lib\netstandard2.0\Microsoft.AspNetCore.Http.Extensions.dll + + + ..\packages\Microsoft.AspNetCore.Http.Features.2.0.3\lib\netstandard2.0\Microsoft.AspNetCore.Http.Features.dll + + + ..\packages\Microsoft.AspNetCore.ResponseCompression.2.0.3\lib\net461\Microsoft.AspNetCore.ResponseCompression.dll + + + ..\packages\Microsoft.AspNetCore.Server.Kestrel.2.0.3\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.dll + + + ..\packages\Microsoft.AspNetCore.Server.Kestrel.Core.2.0.3\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Core.dll + + + ..\packages\Microsoft.AspNetCore.Server.Kestrel.Https.2.0.3\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Https.dll + + + ..\packages\Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.2.0.3\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.dll + + + ..\packages\Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.2.0.3\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.dll + + + ..\packages\Microsoft.AspNetCore.WebSockets.2.0.3\lib\netstandard2.0\Microsoft.AspNetCore.WebSockets.dll + + + ..\packages\Microsoft.AspNetCore.WebUtilities.2.0.3\lib\netstandard2.0\Microsoft.AspNetCore.WebUtilities.dll + + + ..\packages\Microsoft.Data.Sqlite.Core.2.0.1\lib\netstandard2.0\Microsoft.Data.Sqlite.dll + + + ..\packages\Microsoft.EntityFrameworkCore.2.0.3\lib\netstandard2.0\Microsoft.EntityFrameworkCore.dll + + + ..\packages\Microsoft.EntityFrameworkCore.Relational.2.0.3\lib\netstandard2.0\Microsoft.EntityFrameworkCore.Relational.dll + + + ..\packages\Microsoft.EntityFrameworkCore.Sqlite.Core.2.0.3\lib\netstandard2.0\Microsoft.EntityFrameworkCore.Sqlite.dll + + + ..\packages\Microsoft.Extensions.Caching.Abstractions.2.0.2\lib\netstandard2.0\Microsoft.Extensions.Caching.Abstractions.dll + + + ..\packages\Microsoft.Extensions.Caching.Memory.2.0.2\lib\netstandard2.0\Microsoft.Extensions.Caching.Memory.dll + + + ..\packages\Microsoft.Extensions.Configuration.2.0.2\lib\netstandard2.0\Microsoft.Extensions.Configuration.dll + + + ..\packages\Microsoft.Extensions.Configuration.Abstractions.2.0.2\lib\netstandard2.0\Microsoft.Extensions.Configuration.Abstractions.dll + + + ..\packages\Microsoft.Extensions.Configuration.EnvironmentVariables.2.0.2\lib\netstandard2.0\Microsoft.Extensions.Configuration.EnvironmentVariables.dll + + + ..\packages\Microsoft.Extensions.Configuration.FileExtensions.2.0.2\lib\netstandard2.0\Microsoft.Extensions.Configuration.FileExtensions.dll + + + ..\packages\Microsoft.Extensions.Configuration.Json.2.0.2\lib\netstandard2.0\Microsoft.Extensions.Configuration.Json.dll + + + ..\packages\Microsoft.Extensions.DependencyInjection.2.0.0\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.dll + + + ..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.2.0.0\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + ..\packages\Microsoft.Extensions.FileProviders.Abstractions.2.0.1\lib\netstandard2.0\Microsoft.Extensions.FileProviders.Abstractions.dll + + + ..\packages\Microsoft.Extensions.FileProviders.Physical.2.0.1\lib\netstandard2.0\Microsoft.Extensions.FileProviders.Physical.dll + + + ..\packages\Microsoft.Extensions.FileSystemGlobbing.2.0.1\lib\netstandard2.0\Microsoft.Extensions.FileSystemGlobbing.dll + + + ..\packages\Microsoft.Extensions.Hosting.Abstractions.2.0.3\lib\netstandard2.0\Microsoft.Extensions.Hosting.Abstractions.dll + + + ..\packages\Microsoft.Extensions.Logging.2.0.2\lib\netstandard2.0\Microsoft.Extensions.Logging.dll + + + ..\packages\Microsoft.Extensions.Logging.Abstractions.2.0.2\lib\netstandard2.0\Microsoft.Extensions.Logging.Abstractions.dll + + + ..\packages\Microsoft.Extensions.ObjectPool.2.0.0\lib\netstandard2.0\Microsoft.Extensions.ObjectPool.dll + + + ..\packages\Microsoft.Extensions.Options.2.0.2\lib\netstandard2.0\Microsoft.Extensions.Options.dll + + + ..\packages\Microsoft.Extensions.Primitives.2.0.0\lib\netstandard2.0\Microsoft.Extensions.Primitives.dll + + + ..\packages\Microsoft.Net.Http.Headers.2.0.3\lib\netstandard2.0\Microsoft.Net.Http.Headers.dll + + + ..\packages\Neo.2.8.0\lib\net47\Neo.dll + + + ..\packages\Neo.VM.2.3.1\lib\net461\Neo.VM.dll + + + ..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll + + + ..\packages\Remotion.Linq.2.2.0\lib\net45\Remotion.Linq.dll + + + ..\packages\Replicon.Cryptography.SCrypt.1.1.6.13\lib\net40\Replicon.Cryptography.SCrypt.dll + + + ..\packages\SQLitePCLRaw.bundle_green.1.1.11\lib\net45\SQLitePCLRaw.batteries_green.dll + + + ..\packages\SQLitePCLRaw.bundle_green.1.1.11\lib\net45\SQLitePCLRaw.batteries_v2.dll + + + ..\packages\SQLitePCLRaw.core.1.1.11\lib\net45\SQLitePCLRaw.core.dll + + + ..\packages\SQLitePCLRaw.provider.e_sqlite3.net45.1.1.11\lib\net45\SQLitePCLRaw.provider.e_sqlite3.dll + + + + ..\packages\System.Buffers.4.4.0\lib\netstandard2.0\System.Buffers.dll + + + ..\packages\System.Collections.Immutable.1.4.0\lib\netstandard2.0\System.Collections.Immutable.dll + + + ..\packages\System.ComponentModel.Annotations.4.4.1\lib\net461\System.ComponentModel.Annotations.dll + + + + + + ..\packages\System.Diagnostics.DiagnosticSource.4.4.1\lib\net46\System.Diagnostics.DiagnosticSource.dll + + + ..\packages\System.Interactive.Async.3.1.1\lib\net46\System.Interactive.Async.dll + + + + ..\packages\System.Numerics.Vectors.4.4.0\lib\net46\System.Numerics.Vectors.dll + + + ..\packages\System.Reflection.Metadata.1.5.0\lib\netstandard2.0\System.Reflection.Metadata.dll + + + ..\packages\System.Runtime.CompilerServices.Unsafe.4.4.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll + + + + ..\packages\System.Text.Encodings.Web.4.4.0\lib\netstandard2.0\System.Text.Encodings.Web.dll + + + ..\packages\System.Threading.Tasks.Extensions.4.4.0\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll + + + + + + + + + + + + + + + + + + + + + 这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。 + + + + + + + + \ No newline at end of file diff --git a/SGAS.UnitTests/SGASTest.cs b/SGAS.UnitTests/SGASTest.cs new file mode 100644 index 0000000..d0a05d8 --- /dev/null +++ b/SGAS.UnitTests/SGASTest.cs @@ -0,0 +1,312 @@ +using Neo; +using Neo.Core; +using Neo.IO; +using Neo.SmartContract; +using Neo.VM; +using Neo.Wallets; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NeoContract.UnitTests +{ + public static class SGASTest + { + static readonly UInt160 SgasAddress = Wallet.ToScriptHash("AJk6Ugmz2bJGhoye9EAnssvvLghf6YmptA"); + static readonly UInt160 ScriptHash = new UInt160("0x3cfb49c6eb5360440bdd226528ada99e8d419220".Remove(0, 2).HexToBytes().Reverse().ToArray()); + static readonly UInt160 User = Wallet.ToScriptHash("AJd31a8rYPEBkY1QSxpsGy8mdU4vTYTD4U"); + static readonly byte[] UserScript = "2103ad1d70f140d84a90ad4491cdf175fa64bfa9287a006e8cbd8f8db8500b5205baac".HexToBytes(); + + //SGAS MintTokens + public static void MintTokens() + { + var inputs = new List { + //coin reference A + new CoinReference(){ + PrevHash = new UInt256("0xf5088ce508d86197c991ff0ef7651ddf01f3e555f257039c972082250e899210".Remove(0, 2).HexToBytes().Reverse().ToArray()), + PrevIndex = 0 //16639 GAS + } + }.ToArray(); + + var outputs = new List{ new TransactionOutput() + { + AssetId = Blockchain.UtilityToken.Hash, //Asset Id, this is GAS + ScriptHash = SgasAddress, //SGAS 地址 + Value = new Fixed8((long)(1 * (long)Math.Pow(10, 8))) //Value + }}.ToArray(); + + Transaction tx = null; + + using (ScriptBuilder sb = new ScriptBuilder()) + { + sb.EmitAppCall(ScriptHash, "mintTokens"); + sb.Emit(OpCode.THROWIFNOT); + + byte[] nonce = new byte[8]; + Random rand = new Random(); + rand.NextBytes(nonce); + sb.Emit(OpCode.RET, nonce); + tx = new InvocationTransaction + { + Version = 1, + Script = sb.ToArray(), + Outputs = outputs, + Inputs = inputs, + Attributes = new TransactionAttribute[0], + Scripts = new Witness[0] + }; + } + + if (tx == null) + { + Console.WriteLine("Create Transaction Failed"); + Console.ReadLine(); + return; + } + + //Open wallet + var wallet = new Neo.Implementations.Wallets.NEP6.NEP6Wallet("0.json"); + try + { + wallet.Unlock("1"); + } + catch (Exception) + { + Console.WriteLine("password error"); + } + + //Sign in wallet + var context = new ContractParametersContext(tx); + wallet.Sign(context); + if (context.Completed) + { + Console.WriteLine("Sign Successful"); + tx.Scripts = context.GetScripts(); + } + else + { + Console.WriteLine("Sign Faild"); + } + + try + { + tx = Transaction.DeserializeFrom(tx.ToArray()); + } + catch (Exception) + { + Console.WriteLine("Invalid Transaction Format"); + } + + Console.WriteLine("Verify Transaction:" + tx.Verify(new List { tx })); + + Console.WriteLine("Raw Transaction:"); + Console.WriteLine(tx.ToArray().ToHexString()); + + //Then Call neo-cli API:sendrawtransaction in postman. + } + + public static void Refund() + { + var inputs = new List { + new CoinReference(){ + PrevHash = new UInt256("0xdb4c4f1a17b365a68497ef0e118db89b827db24f67ee71d317d38c68c84424ef".Remove(0, 2).HexToBytes().Reverse().ToArray()), + PrevIndex = 0 //1 + } + }.ToArray(); + + var outputs = new List{ new TransactionOutput() + { + AssetId = Blockchain.UtilityToken.Hash, //Asset Id, this is GAS + ScriptHash = SgasAddress, //SGAS 地址 + Value = new Fixed8((long)(1 * (long)Math.Pow(10, 8))) //Value + }}.ToArray(); + + Transaction tx = null; + + var applicationScript = new byte[0]; + + using (ScriptBuilder sb = new ScriptBuilder()) + { + sb.EmitAppCall(ScriptHash, "refund", User); + sb.Emit(OpCode.THROWIFNOT); + applicationScript = sb.ToArray(); + } + + tx = new InvocationTransaction + { + Version = 0, + Script = applicationScript, + Outputs = outputs, + Inputs = inputs, + Attributes = new TransactionAttribute[] + { + new TransactionAttribute + { + Usage = TransactionAttributeUsage.Script, + Data = User.ToArray()//附加人的 Script Hash + } + } + }; + + + if (tx == null) + { + Console.WriteLine("Create Transaction Failed"); + Console.ReadLine(); + return; + } + + //Open wallet + var wallet = new Neo.Implementations.Wallets.NEP6.NEP6Wallet("0.json"); + try + { + wallet.Unlock("1"); + } + catch (Exception) + { + Console.WriteLine("password error"); + } + + //Sign in wallet 生成附加人的签名 + var context = new ContractParametersContext(tx); + var additionalSignature = new byte[0]; + foreach (UInt160 hash in context.ScriptHashes) + { + if (hash == User) + { + WalletAccount account = wallet.GetAccount(hash); + if (account?.HasKey != true) continue; + KeyPair key = account.GetKey(); + additionalSignature = context.Verifiable.Sign(key); + } + } + var additionalVerificationScript = new byte[0]; + using (ScriptBuilder sb = new ScriptBuilder()) + { + sb.EmitPush(additionalSignature); + additionalVerificationScript = sb.ToArray(); + } + var verificationScript = new byte[0]; + using (ScriptBuilder sb = new ScriptBuilder()) + { + sb.EmitPush(2); + sb.EmitPush("1"); + verificationScript = sb.ToArray(); + } + var witness = new Witness + { + InvocationScript = verificationScript, + VerificationScript = Blockchain.Default.GetContract(ScriptHash).Script + }; + var additionalWitness = new Witness + { + InvocationScript = additionalVerificationScript, + VerificationScript = UserScript + }; + var witnesses = new Witness[2] { witness, additionalWitness }; + tx.Scripts = witnesses.ToList().OrderBy(p => p.ScriptHash).ToArray(); + + try + { + tx = Transaction.DeserializeFrom(tx.ToArray()); + } + catch (Exception) + { + Console.WriteLine("Invalid Transaction Format"); + } + + if (tx.Verify(new List { tx })) + { + Console.WriteLine("Verify Transaction: True"); + Console.WriteLine("Raw Transaction:"); + Console.WriteLine(tx.ToArray().ToHexString()); + //Console.WriteLine(tx.ToJson()); + + + //Then Call neo-cli API:sendrawtransaction in postman. + } + else + { + Console.WriteLine("Verify Transaction: False"); + } + } + + public static void Verify() + { + var inputs = new List { + new CoinReference(){ + PrevHash = new UInt256("0xdb4c4f1a17b365a68497ef0e118db89b827db24f67ee71d317d38c68c84424ef".Remove(0, 2).HexToBytes().Reverse().ToArray()), + PrevIndex = 0 //1 + } + }.ToArray(); + + var outputs = new List{ new TransactionOutput() + { + AssetId = Blockchain.UtilityToken.Hash, //Asset Id, this is GAS + ScriptHash = SgasAddress,//SGAS 地址 + Value = new Fixed8((long)(1 * (long)Math.Pow(10, 8))) //Value + }}.ToArray(); + + Transaction tx = null; + + var verificationScript = new byte[0]; + using (ScriptBuilder sb = new ScriptBuilder()) + { + sb.EmitPush(2); + sb.EmitPush("1"); + verificationScript = sb.ToArray(); + } + + var witness = new Witness + { + InvocationScript = verificationScript, + //未部署的合约不能执行 Storage.Get() 方法,所以要将合约部署,而不是调用本地的 AVM 文件 + //VerificationScript = File.ReadAllBytes("C:\\Users\\chenz\\Documents\\1Code\\chenzhitong\\NeoContract5\\NeoContract\\bin\\Debug\\SGAS.avm") + VerificationScript = Blockchain.Default.GetContract(ScriptHash).Script + }; + tx = new InvocationTransaction + { + Version = 0, + Script = new byte[0], + Outputs = outputs, + Inputs = inputs, + Attributes = new TransactionAttribute[0], + Scripts = new Witness[] { witness } + }; + + + if (tx == null) + { + Console.WriteLine("Create Transaction Failed"); + Console.ReadLine(); + return; + } + + try + { + tx = Transaction.DeserializeFrom(tx.ToArray()); + } + catch (Exception) + { + Console.WriteLine("Invalid Transaction Format"); + } + if (tx.Verify(new List { tx })) + { + Console.WriteLine("Verify Transaction: True"); + Console.WriteLine("Raw Transaction:"); + Console.WriteLine(tx.ToArray().ToHexString()); + //Console.WriteLine(tx.ToJson()); + + + //Then Call neo-cli API:sendrawtransaction in postman. + } + else + { + Console.WriteLine("Verify Transaction: False"); + } + } + } +} diff --git a/SGAS.UnitTests/packages.config b/SGAS.UnitTests/packages.config new file mode 100644 index 0000000..233e880 --- /dev/null +++ b/SGAS.UnitTests/packages.config @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Tools/App.config b/Tools/App.config new file mode 100644 index 0000000..731f6de --- /dev/null +++ b/Tools/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Tools/Program.cs b/Tools/Program.cs new file mode 100644 index 0000000..d3b144b --- /dev/null +++ b/Tools/Program.cs @@ -0,0 +1,65 @@ +using Neo; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using System.Text; +using System.Threading.Tasks; + +namespace ConsoleApp1 +{ + static class Program + { + static void Main(string[] args) + { + //address 2 script hash + Console.WriteLine(Neo.Wallets.Wallet.ToScriptHash("AJd31a8rYPEBkY1QSxpsGy8mdU4vTYTD4U")); + //script hash 2 address + Console.WriteLine(Neo.Wallets.Wallet.ToAddress(new UInt160("0xeee76c45175b5af08630b2278a24803368284a1e".Remove(0, 2).HexToBytes().Reverse().ToArray()))); + + //hex string 2 string + Console.WriteLine("7472616e73666572".HexToString()); + //string 2 hex string + Console.WriteLine("transfer".ToHexString()); + + //big-endian 2 little-endian + Console.WriteLine("0x4701ee0b674ff2d8893effc2607be85327733c1f".Remove(0, 2).HexToBytes().Reverse().ToHexString()); + //little-endian 2 big-endian + Console.WriteLine("0x" + "b1ad4a4093e7b918d19b013b7347cf0a67bed8ac6ca393ea9a473841b6ef3523".HexToBytes().Reverse().ToHexString()); + + //hex string 2 biginteger + Console.WriteLine(new BigInteger("00e1f505".HexToBytes())); + //biginteger 2 hex string + Console.WriteLine(new BigInteger(100000000).ToByteArray().ToHexString()); + + Console.ReadLine(); + } + + static string HexToString(this string hex) + { + if (hex.Length % 2 != 0) + { + throw new ArgumentException(); + } + var output = ""; + for (int i = 0; i <= hex.Length - 2; i+=2) + { + try + { + var result = Convert.ToByte(new string(hex.Skip(i).Take(2).ToArray()), 16); + output += (Convert.ToChar(result)); + } + catch (Exception) + { + throw; + } + } + return output; + } + static string ToHexString(this string str) + { + byte[] byteArray = Encoding.Default.GetBytes(str.ToCharArray()); + return byteArray.ToHexString(); + } + } +} diff --git a/Tools/Properties/AssemblyInfo.cs b/Tools/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..298da42 --- /dev/null +++ b/Tools/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("ConsoleApp1")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ConsoleApp1")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("a4f2d281-a2e9-4950-aa18-098bf614fd6c")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +// 方法是按如下所示使用“*”: : +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Tools/Tools.csproj b/Tools/Tools.csproj new file mode 100644 index 0000000..49b56a0 --- /dev/null +++ b/Tools/Tools.csproj @@ -0,0 +1,237 @@ + + + + + Debug + AnyCPU + {A4F2D281-A2E9-4950-AA18-098BF614FD6C} + Exe + ConsoleApp1 + ConsoleApp1 + v4.6.1 + 512 + true + + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\Microsoft.AspNetCore.Hosting.2.0.2\lib\netstandard2.0\Microsoft.AspNetCore.Hosting.dll + + + ..\packages\Microsoft.AspNetCore.Hosting.Abstractions.2.0.2\lib\netstandard2.0\Microsoft.AspNetCore.Hosting.Abstractions.dll + + + ..\packages\Microsoft.AspNetCore.Hosting.Server.Abstractions.2.0.2\lib\netstandard2.0\Microsoft.AspNetCore.Hosting.Server.Abstractions.dll + + + ..\packages\Microsoft.AspNetCore.Http.2.0.2\lib\netstandard2.0\Microsoft.AspNetCore.Http.dll + + + ..\packages\Microsoft.AspNetCore.Http.Abstractions.2.0.2\lib\netstandard2.0\Microsoft.AspNetCore.Http.Abstractions.dll + + + ..\packages\Microsoft.AspNetCore.Http.Extensions.2.0.2\lib\netstandard2.0\Microsoft.AspNetCore.Http.Extensions.dll + + + ..\packages\Microsoft.AspNetCore.Http.Features.2.0.2\lib\netstandard2.0\Microsoft.AspNetCore.Http.Features.dll + + + ..\packages\Microsoft.AspNetCore.ResponseCompression.2.0.2\lib\net461\Microsoft.AspNetCore.ResponseCompression.dll + + + ..\packages\Microsoft.AspNetCore.Server.Kestrel.2.0.2\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.dll + + + ..\packages\Microsoft.AspNetCore.Server.Kestrel.Core.2.0.2\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Core.dll + + + ..\packages\Microsoft.AspNetCore.Server.Kestrel.Https.2.0.2\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Https.dll + + + ..\packages\Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.2.0.2\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.dll + + + ..\packages\Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.2.0.2\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.dll + + + ..\packages\Microsoft.AspNetCore.WebSockets.2.0.2\lib\netstandard2.0\Microsoft.AspNetCore.WebSockets.dll + + + ..\packages\Microsoft.AspNetCore.WebUtilities.2.0.2\lib\netstandard2.0\Microsoft.AspNetCore.WebUtilities.dll + + + ..\packages\Microsoft.Data.Sqlite.Core.2.0.1\lib\netstandard2.0\Microsoft.Data.Sqlite.dll + + + ..\packages\Microsoft.EntityFrameworkCore.2.0.2\lib\netstandard2.0\Microsoft.EntityFrameworkCore.dll + + + ..\packages\Microsoft.EntityFrameworkCore.Relational.2.0.2\lib\netstandard2.0\Microsoft.EntityFrameworkCore.Relational.dll + + + ..\packages\Microsoft.EntityFrameworkCore.Sqlite.Core.2.0.2\lib\netstandard2.0\Microsoft.EntityFrameworkCore.Sqlite.dll + + + ..\packages\Microsoft.Extensions.Caching.Abstractions.2.0.1\lib\netstandard2.0\Microsoft.Extensions.Caching.Abstractions.dll + + + ..\packages\Microsoft.Extensions.Caching.Memory.2.0.1\lib\netstandard2.0\Microsoft.Extensions.Caching.Memory.dll + + + ..\packages\Microsoft.Extensions.Configuration.2.0.1\lib\netstandard2.0\Microsoft.Extensions.Configuration.dll + + + ..\packages\Microsoft.Extensions.Configuration.Abstractions.2.0.1\lib\netstandard2.0\Microsoft.Extensions.Configuration.Abstractions.dll + + + ..\packages\Microsoft.Extensions.Configuration.EnvironmentVariables.2.0.1\lib\netstandard2.0\Microsoft.Extensions.Configuration.EnvironmentVariables.dll + + + ..\packages\Microsoft.Extensions.Configuration.FileExtensions.2.0.1\lib\netstandard2.0\Microsoft.Extensions.Configuration.FileExtensions.dll + + + ..\packages\Microsoft.Extensions.Configuration.Json.2.0.1\lib\netstandard2.0\Microsoft.Extensions.Configuration.Json.dll + + + ..\packages\Microsoft.Extensions.DependencyInjection.2.0.0\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.dll + + + ..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.2.0.0\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + ..\packages\Microsoft.Extensions.FileProviders.Abstractions.2.0.1\lib\netstandard2.0\Microsoft.Extensions.FileProviders.Abstractions.dll + + + ..\packages\Microsoft.Extensions.FileProviders.Physical.2.0.1\lib\netstandard2.0\Microsoft.Extensions.FileProviders.Physical.dll + + + ..\packages\Microsoft.Extensions.FileSystemGlobbing.2.0.1\lib\netstandard2.0\Microsoft.Extensions.FileSystemGlobbing.dll + + + ..\packages\Microsoft.Extensions.Hosting.Abstractions.2.0.2\lib\netstandard2.0\Microsoft.Extensions.Hosting.Abstractions.dll + + + ..\packages\Microsoft.Extensions.Logging.2.0.1\lib\netstandard2.0\Microsoft.Extensions.Logging.dll + + + ..\packages\Microsoft.Extensions.Logging.Abstractions.2.0.1\lib\netstandard2.0\Microsoft.Extensions.Logging.Abstractions.dll + + + ..\packages\Microsoft.Extensions.ObjectPool.2.0.0\lib\netstandard2.0\Microsoft.Extensions.ObjectPool.dll + + + ..\packages\Microsoft.Extensions.Options.2.0.1\lib\netstandard2.0\Microsoft.Extensions.Options.dll + + + ..\packages\Microsoft.Extensions.Primitives.2.0.0\lib\netstandard2.0\Microsoft.Extensions.Primitives.dll + + + ..\packages\Microsoft.Net.Http.Headers.2.0.2\lib\netstandard2.0\Microsoft.Net.Http.Headers.dll + + + ..\packages\Neo.2.7.6.1\lib\netstandard2.0\Neo.dll + + + ..\packages\Neo.VM.2.2.0\lib\net461\Neo.VM.dll + + + ..\packages\Newtonsoft.Json.10.0.1\lib\net45\Newtonsoft.Json.dll + + + ..\packages\Remotion.Linq.2.1.1\lib\net45\Remotion.Linq.dll + + + ..\packages\SQLitePCLRaw.bundle_green.1.1.7\lib\net45\SQLitePCLRaw.batteries_green.dll + + + ..\packages\SQLitePCLRaw.bundle_green.1.1.7\lib\net45\SQLitePCLRaw.batteries_v2.dll + + + ..\packages\SQLitePCLRaw.core.1.1.7\lib\net45\SQLitePCLRaw.core.dll + + + ..\packages\SQLitePCLRaw.provider.e_sqlite3.net45.1.1.7\lib\net45\SQLitePCLRaw.provider.e_sqlite3.dll + + + + ..\packages\System.Buffers.4.4.0\lib\netstandard2.0\System.Buffers.dll + + + ..\packages\System.Collections.Immutable.1.4.0\lib\netstandard2.0\System.Collections.Immutable.dll + + + ..\packages\System.ComponentModel.Annotations.4.4.0\lib\net461\System.ComponentModel.Annotations.dll + + + + + + ..\packages\System.Diagnostics.DiagnosticSource.4.4.1\lib\net46\System.Diagnostics.DiagnosticSource.dll + + + ..\packages\System.Interactive.Async.3.1.1\lib\net46\System.Interactive.Async.dll + + + + ..\packages\System.Numerics.Vectors.4.4.0\lib\net46\System.Numerics.Vectors.dll + + + ..\packages\System.Reflection.Metadata.1.5.0\lib\netstandard2.0\System.Reflection.Metadata.dll + + + ..\packages\System.Runtime.CompilerServices.Unsafe.4.4.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll + + + ..\packages\System.Text.Encodings.Web.4.4.0\lib\netstandard2.0\System.Text.Encodings.Web.dll + + + ..\packages\System.Threading.Tasks.Extensions.4.4.0\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll + + + + + + + + + + + + + + + + + + + + + 这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。 + + + + + + + + \ No newline at end of file diff --git a/Tools/packages.config b/Tools/packages.config new file mode 100644 index 0000000..4ebf2fb --- /dev/null +++ b/Tools/packages.config @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..f974a7c --- /dev/null +++ b/readme.md @@ -0,0 +1,45 @@ +## Unit test result + +Test environment: + +private net + +neo-cli 2.7.6 (must > 2.7.5) + +neo-gui 2.7.6 + +| Method | Description | How to test | Test Result | +| ------------------------ | ---------------------------------- | ------------------------------ | ----------- | +| balanceOf | see nep-5 | neo-gui | ✅ | +| decimals | see nep-5 | neo-gui | ✅ | +| getRefundTarget | get who want to refund this UTXO | neo-gui | ✅ | +| getTxInfo | get tx info | neo-gui | ✅ | +| mintTokens | GAS → SGAS | c# code + neo-cli | ✅ | +| name | see nep-5 | neo-gui | ✅ | +| refund | SGAS → GAS 1/2 step | c# code + neo-cli | ✅ | +| symbol | see nep-5 | neo-gui | ✅ | +| totalSupply | see nep-5 | neo-gui | ✅ | +| transfer | see nep-5 | neo-gui or neo-cli | ✅ | +| transferAPP | transfer from other smart contract | neo-gui + other smart contract | ✅ | +| TriggerType.Verification | | c# code + neo-cli | ✅ | + +Useful Test Tools: [https://github.com/chenzhitong/ApplicationLogsTools](https://github.com/chenzhitong/ApplicationLogsTools) + +备注: + +Verification 触发器执行时如果有参数需要传参,否则会因为栈不平而失败 + +Verification 触发器的参数要放在交易的 Witness 的 InvocationScript 字段中,可以用 ScriptBuilder 来构造 + +Verification 触发器中不能执行下面的代码 +var callscript = ExecutionEngine.CallingScriptHash; + +未部署的合约不能执行 Storage.Get() 方法 + +Storage.Get() 如果查询不到的话,返回 byte[0] 而不是 null + +Application 触发器中如果调用 CheckWitness() 的话,需要在 TransactionAttribute 中传附加人的签名 Usage = TransactionAttributeUsage.Script Data = ScriptHash,并且在 Scripts 中添加一个新的 Witness + +推荐使用 StorageMap 来读写存储区,而不是直接用 Storage.Get 或 Storage.Put + +NEP-5 中,参数错误应该抛出异常,而不是返回 false