├── .gitattributes ├── .gitignore ├── .prettierrc ├── .solhint.json ├── .yarnrc ├── LICENSE ├── README.md ├── contracts ├── EmblemWeaver.sol ├── FieldGenerator.sol ├── FrameGenerator.sol ├── HardwareGenerator.sol ├── SVGs │ ├── Fields │ │ ├── FieldSVGs1.sol │ │ ├── FieldSVGs10.sol │ │ ├── FieldSVGs11.sol │ │ ├── FieldSVGs12.sol │ │ ├── FieldSVGs13.sol │ │ ├── FieldSVGs14.sol │ │ ├── FieldSVGs15.sol │ │ ├── FieldSVGs16.sol │ │ ├── FieldSVGs17.sol │ │ ├── FieldSVGs18.sol │ │ ├── FieldSVGs19.sol │ │ ├── FieldSVGs2.sol │ │ ├── FieldSVGs20.sol │ │ ├── FieldSVGs21.sol │ │ ├── FieldSVGs22.sol │ │ ├── FieldSVGs23.sol │ │ ├── FieldSVGs24.sol │ │ ├── FieldSVGs3.sol │ │ ├── FieldSVGs4.sol │ │ ├── FieldSVGs5.sol │ │ ├── FieldSVGs6.sol │ │ ├── FieldSVGs7.sol │ │ ├── FieldSVGs8.sol │ │ └── FieldSVGs9.sol │ ├── Frames │ │ ├── FrameSVGs1.sol │ │ └── FrameSVGs2.sol │ ├── Hardware │ │ ├── HardwareSVGs1.sol │ │ ├── HardwareSVGs10.sol │ │ ├── HardwareSVGs11.sol │ │ ├── HardwareSVGs12.sol │ │ ├── HardwareSVGs13.sol │ │ ├── HardwareSVGs14.sol │ │ ├── HardwareSVGs15.sol │ │ ├── HardwareSVGs16.sol │ │ ├── HardwareSVGs17.sol │ │ ├── HardwareSVGs18.sol │ │ ├── HardwareSVGs19.sol │ │ ├── HardwareSVGs2.sol │ │ ├── HardwareSVGs20.sol │ │ ├── HardwareSVGs21.sol │ │ ├── HardwareSVGs22.sol │ │ ├── HardwareSVGs23.sol │ │ ├── HardwareSVGs24.sol │ │ ├── HardwareSVGs25.sol │ │ ├── HardwareSVGs26.sol │ │ ├── HardwareSVGs27.sol │ │ ├── HardwareSVGs28.sol │ │ ├── HardwareSVGs29.sol │ │ ├── HardwareSVGs3.sol │ │ ├── HardwareSVGs30.sol │ │ ├── HardwareSVGs31.sol │ │ ├── HardwareSVGs32.sol │ │ ├── HardwareSVGs33.sol │ │ ├── HardwareSVGs34.sol │ │ ├── HardwareSVGs35.sol │ │ ├── HardwareSVGs36.sol │ │ ├── HardwareSVGs37.sol │ │ ├── HardwareSVGs38.sol │ │ ├── HardwareSVGs4.sol │ │ ├── HardwareSVGs5.sol │ │ ├── HardwareSVGs6.sol │ │ ├── HardwareSVGs7.sol │ │ ├── HardwareSVGs8.sol │ │ └── HardwareSVGs9.sol │ └── ShieldBadgeSVGs.sol ├── Shields.sol ├── interfaces │ ├── ICategories.sol │ ├── IColors.sol │ ├── IEmblemWeaver.sol │ ├── IFieldGenerator.sol │ ├── IFieldSVGs.sol │ ├── IFrameGenerator.sol │ ├── IFrameSVGs.sol │ ├── IHardwareGenerator.sol │ ├── IHardwareSVGs.sol │ ├── IShieldBadgeSVGs.sol │ └── IShields.sol ├── libraries │ └── HexStrings.sol └── test │ ├── EmblemWeaverTest.sol │ ├── ShieldsGasTest.sol │ ├── ShieldsTest.sol │ ├── TestFieldGenerator.sol │ └── TestHardwareGenerator.sol ├── deploy ├── 01_deploy_field_generator.ts ├── 02_deploy_hardware_generator.ts ├── 03_deploy_frame_generator.ts ├── 04_deploy_shieldbadgesvgs.ts ├── 05_deploy_emblem_weaver.ts ├── 06_deploy_shields.ts └── 07_transfer_ownership.ts ├── deploySVGs ├── deployFieldSVGs.ts ├── deployedSVGs.json └── helpers.ts ├── deployments ├── goerli │ ├── .chainId │ ├── BuildPassSVGs.json │ ├── FieldGenerator.json │ ├── FrameGenerator.json │ ├── HardwareGenerator.json │ ├── ShieldDescriptor.json │ ├── Shields.json │ └── solcInputs │ │ ├── 0ac3b406cc563db62fbf6a074b8a54e1.json │ │ ├── 120b7981f2664f557f778127eaf1c6ed.json │ │ ├── 5bfe4b77149d6f73b152c3b333b753f0.json │ │ ├── b18099829130d9e20f6eb2b1e8b44ffc.json │ │ ├── f13209de5f6765da42f325a73fb27d59.json │ │ └── f83fc13fabc733ee8b83028c3110d7b0.json ├── mainnet │ ├── .chainId │ ├── EmblemWeaver.json │ ├── FieldGenerator.json │ ├── FrameGenerator.json │ ├── HardwareGenerator.json │ ├── ShieldBadgeSVGs.json │ ├── Shields.json │ └── solcInputs │ │ ├── 06c6c0124c47c1cdc59e63dde81c06b1.json │ │ ├── 09befa56f4355a6ca3989fb006f2f0b3.json │ │ ├── 132b2a838ee2991bd733956c8b035354.json │ │ ├── 53fca273d67f718f5cb0758c3ff9defc.json │ │ └── d28a8c5f5f1014153754a39e08baa75b.json └── rinkeby │ ├── .chainId │ ├── BuildPassSVGs.json │ ├── EmblemWeaver.json │ ├── FieldGenerator.json │ ├── FrameGenerator.json │ ├── HardwareGenerator.json │ ├── ShieldBadgeSVGs.json │ ├── ShieldDescriptor.json │ ├── Shields.json │ └── solcInputs │ ├── 06c6c0124c47c1cdc59e63dde81c06b1.json │ ├── 09befa56f4355a6ca3989fb006f2f0b3.json │ ├── 0ac3b406cc563db62fbf6a074b8a54e1.json │ ├── 132b2a838ee2991bd733956c8b035354.json │ ├── 32c3c77c4b2b5be30d2bd140bb4ee998.json │ ├── 39707df8ab59bdff5775ed0c387546b7.json │ ├── 3f384c0dfe2328302ebd4d9888e64775.json │ ├── 53fca273d67f718f5cb0758c3ff9defc.json │ ├── 5bfe4b77149d6f73b152c3b333b753f0.json │ ├── 7b1bbcd7f29fa3ba20bf06fb65a1b0f9.json │ ├── 97250a4cdb9387cee9c1bfaceb096ed2.json │ ├── a9e7d4fcf53118db8118fcbd76e082b4.json │ ├── b18099829130d9e20f6eb2b1e8b44ffc.json │ ├── d28a8c5f5f1014153754a39e08baa75b.json │ ├── d69528a4b69a6281f4bad594fdf80357.json │ └── fe897b961f7bc28b8df8819c7790723a.json ├── fields.txt ├── hardhat.config.ts ├── package.json ├── test ├── EmblemWeaver.spec.ts ├── FieldSVGs.spec.ts ├── FrameSVGs.spec.ts ├── HardwareSVGs.spec.ts ├── Shields.spec.ts ├── __snapshots__ │ ├── EmblemWeaver.spec.ts.snap │ ├── FieldSVGs.spec.ts.snap │ ├── FrameSVGs.spec.ts.snap │ ├── HardwareSVGs.spec.ts.snap │ ├── ShieldDescriptor.spec.ts.snap │ ├── Shields.spec.ts.snap │ └── svgs │ │ ├── .DS_Store │ │ ├── fields │ │ ├── 000_Perfect.svg │ │ ├── 001_Per Pale.svg │ │ ├── 002_Per Fess.svg │ │ ├── 003_Per Bend Sinister.svg │ │ ├── 004_Quarterly I.svg │ │ ├── 005_Per Saltire.svg │ │ ├── 006_Gyronny.svg │ │ ├── 007_Per Chevron.svg │ │ ├── 008_Per Chevron Inverted.svg │ │ ├── 009_Per Chevron Ployé.svg │ │ ├── 010_Per Chevron Inverted Ployé.svg │ │ ├── 011_Per Pale Indented.svg │ │ ├── 012_Per Pale Raguly.svg │ │ ├── 013_Per Pale Embattled .svg │ │ ├── 014_Per Pale Wavy.svg │ │ ├── 015_Per Pale Rayonny.svg │ │ ├── 016_Per Pale Nebuly.svg │ │ ├── 017_Per Pall Nebuly II.svg │ │ ├── 018_Per Pale Indented Pometty.svg │ │ ├── 019_Per Fess Indented.svg │ │ ├── 020_Per Fess Raguly.svg │ │ ├── 021_Per Fess Embattled.svg │ │ ├── 022_Per Fess Wavy.svg │ │ ├── 023_Per Fess Rayonny.svg │ │ ├── 024_Per Fess Nebuly I.svg │ │ ├── 025_Per Fess Nebuly II.svg │ │ ├── 026_Per Fess Indented Pometty.svg │ │ ├── 027_Per Fess with a Left Step.svg │ │ ├── 028_Per Fess Enarched.svg │ │ ├── 029_Per Bend Sinister Engrailed.svg │ │ ├── 030_Per Bend Sinister Wavy.svg │ │ ├── 031_Per Bend Sinister Bevilled.svg │ │ ├── 032_Quarterly Embattled.svg │ │ ├── 033_Quarterly Arrondi.svg │ │ ├── 034_Gyronny Arrondi of Twelve.svg │ │ ├── 035_Gyronny From Base.svg │ │ ├── 036_Gyronny From Chief.svg │ │ ├── 037_Gyronny Wavy I.svg │ │ ├── 038_Per Chevron Embattled.svg │ │ ├── 039_Pale I.svg │ │ ├── 040_Pale II.svg │ │ ├── 041_Pale Engrailed.svg │ │ ├── 042_Pale Lozengy.svg │ │ ├── 043_Pale Nebuly.svg │ │ ├── 044_Pale Offset.svg │ │ ├── 045_Pale Embattled.svg │ │ ├── 046_Pale Raguly.svg │ │ ├── 047_Pale Wavy I.svg │ │ ├── 048_Pale Wavy II.svg │ │ ├── 049_Pale Bevilled.svg │ │ ├── 050_Fess.svg │ │ ├── 051_Fess Engrailed.svg │ │ ├── 052_Fess Lozengy.svg │ │ ├── 053_Fess Raguly.svg │ │ ├── 054_Fess Wavy.svg │ │ ├── 055_Fess Rayonny.svg │ │ ├── 056_Bend Sinister I.svg │ │ ├── 057_Bend Sinister II.svg │ │ ├── 058_Bend Sinister Engrailed.svg │ │ ├── 059_Bend Sinister Ragully.svg │ │ ├── 060_Bend Sinister Wavy.svg │ │ ├── 061_Bordure.svg │ │ ├── 062_Bordure Engrailed.svg │ │ ├── 063_Bordure Indented.svg │ │ ├── 064_Bordure Embattled.svg │ │ ├── 065_Bordure Wavy.svg │ │ ├── 066_Bordure Rayonny.svg │ │ ├── 067_Razor Bordure.svg │ │ ├── 068_Canton.svg │ │ ├── 069_Canton Sinister.svg │ │ ├── 070_Chief.svg │ │ ├── 071_Chief Engrailed.svg │ │ ├── 072_Chief Indented.svg │ │ ├── 073_Chief Nebuly.svg │ │ ├── 074_Chief Embattled.svg │ │ ├── 075_Chief Wavy.svg │ │ ├── 076_Chief Rayonny.svg │ │ ├── 077_Chief Triangular.svg │ │ ├── 078_Chief Urdy.svg │ │ ├── 079_Base.svg │ │ ├── 080_Base Engrailed.svg │ │ ├── 081_Base Indented.svg │ │ ├── 082_Base Nebuly.svg │ │ ├── 083_Base Embattled.svg │ │ ├── 084_Base Wavy.svg │ │ ├── 085_Base Rayonny.svg │ │ ├── 086_Cross I.svg │ │ ├── 087_Cross II.svg │ │ ├── 088_Cross Engrailed.svg │ │ ├── 089_Saltire.svg │ │ ├── 090_Saltire Engrailed.svg │ │ ├── 091_Chevron I.svg │ │ ├── 092_Chevron II.svg │ │ ├── 093_Chevron Embattled.svg │ │ ├── 094_Chevron Inverted I.svg │ │ ├── 095_Chevron Inverted II.svg │ │ ├── 096_Two Bars.svg │ │ ├── 097_Three Bars.svg │ │ ├── 098_Four Bars.svg │ │ ├── 099_Two Pallets.svg │ │ ├── 100_Three Pallets.svg │ │ ├── 101_Four Pallets.svg │ │ ├── 102_Two Pales Engrailed.svg │ │ ├── 103_Two Pales Nebuly.svg │ │ ├── 104_Two Pales Wavy I.svg │ │ ├── 105_Two Pales Wavy II.svg │ │ ├── 106_Two Pales Dancetty.svg │ │ ├── 107_Orle.svg │ │ ├── 108_Orle Embattled.svg │ │ ├── 109_Pall.svg │ │ ├── 110_Pall Inverted.svg │ │ ├── 111_Pile.svg │ │ ├── 112_Pile Ployé.svg │ │ ├── 113_Pile Inverted.svg │ │ ├── 114_Pile Inverted Ployé.svg │ │ ├── 115_Two Piles.svg │ │ ├── 116_Flaunches.svg │ │ ├── 117_Gyron.svg │ │ ├── 118_Chief Pale.svg │ │ ├── 119_Tierce.svg │ │ ├── 120_Tierce Sinister.svg │ │ ├── 121_Tierces.svg │ │ ├── 122_Gore.svg │ │ ├── 123_Gore Sinister.svg │ │ ├── 124_Gores.svg │ │ ├── 125_Paly of Four.svg │ │ ├── 126_Paly of Eight.svg │ │ ├── 127_Paly Dancetty.svg │ │ ├── 128_Paly Embattled.svg │ │ ├── 129_Paly Wavy I.svg │ │ ├── 130_Paly Wavy II.svg │ │ ├── 131_Barry of Four.svg │ │ ├── 132_Barry of Eight.svg │ │ ├── 133_Barry Dancetty.svg │ │ ├── 134_Barry Embattled.svg │ │ ├── 135_Barry Wavy I.svg │ │ ├── 136_Barry Wavy II.svg │ │ ├── 137_Checky I.svg │ │ ├── 138_Checky II.svg │ │ ├── 139_Checky III.svg │ │ ├── 140_Checky IV.svg │ │ ├── 141_Checky V.svg │ │ ├── 142_Bendy Sinister I.svg │ │ ├── 143_Bendy Sinister II.svg │ │ ├── 144_Bendy Sinister III.svg │ │ ├── 145_Bendy Sinister IV.svg │ │ ├── 146_Chevronny I.svg │ │ ├── 147_Chevronny II.svg │ │ ├── 148_Chevronny Inverted I.svg │ │ ├── 149_Chevronny Inverted II.svg │ │ ├── 150_Lozengy I.svg │ │ ├── 151_Lozengy II.svg │ │ ├── 152_Lozengy Wide.svg │ │ ├── 153_Lozengy Barry.svg │ │ ├── 154_Fusilly I.svg │ │ ├── 155_Fusilly II.svg │ │ ├── 156_Fusilly III.svg │ │ ├── 157_Pily I.svg │ │ ├── 158_Pily II.svg │ │ ├── 159_Orly.svg │ │ ├── 160_Roundel.svg │ │ ├── 161_Annulet.svg │ │ ├── 162_Billet.svg │ │ ├── 163_Triangle.svg │ │ ├── 164_Inescutcheon.svg │ │ ├── 165_Lozenge.svg │ │ ├── 166_Mascle.svg │ │ ├── 167_Mullet.svg │ │ ├── 168_Quatrefoil.svg │ │ ├── 169_Quasar.svg │ │ ├── 170_Three Roundels.svg │ │ ├── 171_Three Quatrefoils.svg │ │ ├── 172_Semy of Roundels.svg │ │ ├── 173_Biletty.svg │ │ ├── 174_Semy of Quatrefoils.svg │ │ ├── 175_Semy-de-Lis.svg │ │ ├── 176_Estencelly.svg │ │ ├── 177_Mullety.svg │ │ ├── 178_Papellony.svg │ │ ├── 179_Masoned.svg │ │ ├── 180_Fretty I.svg │ │ ├── 181_Fretty II.svg │ │ ├── 182_Grillage.svg │ │ ├── 183_Vair.svg │ │ ├── 184_Counter-Vair.svg │ │ ├── 185_Vair Ancient.svg │ │ ├── 186_Per Pale and Per Chevron.svg │ │ ├── 187_Per Pale and Per Fess Indented.svg │ │ ├── 188_Per Fess and Per Pale Wavy.svg │ │ ├── 189_Per Saltire and Per Fess.svg │ │ ├── 190_Per Pale and Barry of Four.svg │ │ ├── 191_Per Pale and Barry of Eight.svg │ │ ├── 192_Per Fess and Paly of Five.svg │ │ ├── 193_Per Fess and Two Pallets.svg │ │ ├── 194_Cross and Saltire I.svg │ │ ├── 195_Grid.svg │ │ ├── 196_Supergrid I.svg │ │ ├── 197_Supergrid II.svg │ │ ├── 198_Microdot.svg │ │ ├── 199_Ehrenstein.svg │ │ ├── 200_Semy of Alternating Roundels.svg │ │ ├── 201_Quasar Semy.svg │ │ ├── 202_Tiles V.svg │ │ ├── 203_QuiltX I.svg │ │ ├── 204_Bloomy.svg │ │ ├── 205_Talon Matrix I.svg │ │ ├── 206_Doppler.svg │ │ ├── 207_Nine Rings.svg │ │ ├── 208_Ripple.svg │ │ ├── 209_Spiral.svg │ │ ├── 210_Rasterwave Pallets.svg │ │ ├── 211_Rasterlines Barry.svg │ │ ├── 212_Rasterlines Bend Sinister.svg │ │ ├── 213_Rasterlines Pale Horizon.svg │ │ ├── 214_Rasterlines Barry and Bendy Sinister.svg │ │ ├── 215_Rasterlines Barry-X.svg │ │ ├── 216_Gyronny Wavy II.svg │ │ ├── 217_Hypno.svg │ │ ├── 218_Infinigyron.svg │ │ ├── 219_Laser.svg │ │ ├── 220_Laser and Boxes Countercharged.svg │ │ ├── 221_Quadrobeams.svg │ │ ├── 222_Laserwheels.svg │ │ ├── 223_Gyronny and Orly.svg │ │ ├── 224_Flex Checky.svg │ │ ├── 225_Hyperbend.svg │ │ ├── 226_Burst.svg │ │ ├── 227_Shattered.svg │ │ ├── 228_Warp.svg │ │ ├── 229_Mach.svg │ │ ├── 230_Kaleidoscope.svg │ │ ├── 231_AxoPile.svg │ │ ├── 232_Lens.svg │ │ ├── 233_Bender.svg │ │ ├── 234_Stretcher.svg │ │ ├── 235_Inner Sphere.svg │ │ ├── 236_Stepper.svg │ │ ├── 237_Per Bend Sinister Hand.svg │ │ ├── 238_Per Pale Indented Hand.svg │ │ ├── 239_Pall Inverted Hand.svg │ │ ├── 240_Orle Hand.svg │ │ ├── 241_Five Pallets Hand.svg │ │ ├── 242_Per Pall.svg │ │ ├── 243_Per Pall Inverted.svg │ │ ├── 244_Tierced Per Pale.svg │ │ ├── 245_Tierced per Fess.svg │ │ ├── 246_Tierced per Bend Sinister.svg │ │ ├── 247_Tierced Per Pale and Per Fess I.svg │ │ ├── 248_Tierced Per Pale and Per Fess II.svg │ │ ├── 249_Pale Checky.svg │ │ ├── 250_Bordure Compony.svg │ │ ├── 251_Bordure Parted Bordurewise.svg │ │ ├── 252_Bordure Counter-Compony.svg │ │ ├── 253_Cross Cotised.svg │ │ ├── 254_Saltire Cotised.svg │ │ ├── 255_Orle on a Bordure.svg │ │ ├── 256_Pall Cotised.svg │ │ ├── 257_Pall Inverted Cotised.svg │ │ ├── 258_Fretty Parted.svg │ │ ├── 259_Party of Eight.svg │ │ ├── 260_Three Quatrefoils on a Chief.svg │ │ ├── 261_Cross on a Chief.svg │ │ ├── 262_Saltire on a Chief.svg │ │ ├── 263_Rising Sun on a Chief.svg │ │ ├── 264_Tierces and Three Quatrefoils.svg │ │ ├── 265_Three Quatrefoils on a Bend.svg │ │ ├── 266_Saltire on a Canton.svg │ │ ├── 267_Gyronny Saltire.svg │ │ ├── 268_Eight-pointed Star on a Cross and Saltire Engrailed.svg │ │ ├── 269_Cross and Saltire II.svg │ │ ├── 270_Saltire Engrailed on a Saltire.svg │ │ ├── 271_Per Saltire and a Saltire.svg │ │ ├── 272_Quarterly, Perfect and Quarterly.svg │ │ ├── 273_Quarterly, Perfect and Check.svg │ │ ├── 274_Quarterly, Perfect and a Bend Sinister.svg │ │ ├── 275_Quarterly, Perfect and Per Bend Sinister.svg │ │ ├── 276_Quarterly, Perfect and a Saltire.svg │ │ ├── 277_Per Pale, Perfect and Barry of Eight.svg │ │ ├── 278_Per Pale, Semy of Ten Four-pointed Stars and Barry of Eight.svg │ │ ├── 279_Per Pale, Paly of Eight and Perfect.svg │ │ ├── 280_Semy of Sixteen Quatrefoils and a Chief.svg │ │ ├── 281_Semy of Eighteen Four-pointed Stars and a Base.svg │ │ ├── 282_Fixture.svg │ │ ├── 283_Net.svg │ │ ├── 284_Reticle.svg │ │ ├── 285_Sparkle.svg │ │ ├── 286_Talon Matrix II.svg │ │ ├── 287_Tiles I.svg │ │ ├── 288_Tiles IV.svg │ │ ├── 289_Xanom.svg │ │ ├── 290_QuiltX II.svg │ │ ├── 291_Cubey I.svg │ │ ├── 292_Cubey II.svg │ │ ├── 293_Quarterly II.svg │ │ ├── 294_Quarterly, a Cross and a Bar.svg │ │ ├── 295_Per Pall Inverted and a Chief.svg │ │ ├── 296_Per Pall Inverted and Chevronelly.svg │ │ ├── 297_Check.svg │ │ ├── 298_Tiles II.svg │ │ └── 299_Tiles III.svg │ │ ├── frame.svg │ │ ├── frames │ │ ├── 000_.svg │ │ ├── 001_Adorned.svg │ │ ├── 002_Menacing.svg │ │ ├── 003_Secured.svg │ │ ├── 004_Floriated.svg │ │ └── 005_Everlasting.svg │ │ ├── hardware.svg │ │ └── hardware │ │ ├── 000_Bushing Hammer.svg │ │ ├── 001_Shovel.svg │ │ ├── 002_Screw.svg │ │ ├── 003_Flathead Screwdriver.svg │ │ ├── 004_Pen Nib.svg │ │ ├── 005_Scissors.svg │ │ ├── 006_Compass.svg │ │ ├── 007_Gear.svg │ │ ├── 008_Tongs.svg │ │ ├── 009_Compass and Triangle.svg │ │ ├── 010_Magnifying Glass.svg │ │ ├── 011_Shears.svg │ │ ├── 012_End Cutting Pliers.svg │ │ ├── 013_Wheel.svg │ │ ├── 014_Tuning Fork.svg │ │ ├── 015_Mallet with Chisels in Saltire.svg │ │ ├── 016_Hammer and Compass.svg │ │ ├── 017_Spring Caliper.svg │ │ ├── 018_Book.svg │ │ ├── 019_Calipers.svg │ │ ├── 020_Three Nails.svg │ │ ├── 021_Awl.svg │ │ ├── 022_French Key Wrench.svg │ │ ├── 023_Pocketwatch.svg │ │ ├── 024_Anvil.svg │ │ ├── 025_Crozier.svg │ │ ├── 026_Jackhammer.svg │ │ ├── 027_Jewelers Loupe.svg │ │ ├── 028_Fasces.svg │ │ ├── 029_Cauldron.svg │ │ ├── 030_Horseshoe and Star.svg │ │ ├── 031_Lug Wrench and Four Lug Nuts.svg │ │ ├── 032_Masonry Trowel and Brickwork.svg │ │ ├── 033_Rudder.svg │ │ ├── 034_Gavel.svg │ │ ├── 035_Tongs and Hammer.svg │ │ ├── 036_Pen Tool.svg │ │ ├── 037_Triskele Tracery.svg │ │ ├── 037_Triskele.svg │ │ ├── 038_Quatrefoil and Three Books in Chief.svg │ │ ├── 039_Keyhole.svg │ │ ├── 040_Pitcher.svg │ │ ├── 041_Piston.svg │ │ ├── 042_Scales.svg │ │ ├── 043_Pulleys.svg │ │ ├── 044_Gears.svg │ │ ├── 045_Astrolabe.svg │ │ ├── 046_Laser Level.svg │ │ ├── 047_Wheatstalk and Two Suns.svg │ │ ├── 048_Shipwheel.svg │ │ ├── 049_Pipe Organ.svg │ │ ├── 050_Knight.svg │ │ ├── 051_Garb.svg │ │ ├── 052_Anchor.svg │ │ ├── 053_Bells.svg │ │ ├── 054_Stack.svg │ │ ├── 055_Orb.svg │ │ ├── 056_Command in Canton.svg │ │ ├── 057_Three Chalices.svg │ │ ├── 058_Three Brushes.svg │ │ ├── 059_Three Writing Pens.svg │ │ ├── 060_Lead Holder and Twin Blades.svg │ │ ├── 061_Scyths Saltire and Treestump.svg │ │ ├── 062_Mining Helmet and Picks Saltire.svg │ │ ├── 063_Flower Pot.svg │ │ ├── 064_Pickaxes.svg │ │ ├── 065_Three Bells in Chief.svg │ │ ├── 066_Three Suns in Chief.svg │ │ ├── 067_Quatrefoil Tracery in Chief.svg │ │ ├── 068_Two Suns.svg │ │ ├── 069_Four Suns.svg │ │ ├── 070_Two Books.svg │ │ ├── 071_Orle of Chains.svg │ │ ├── 072_Crancelin.svg │ │ ├── 073_Four Wheels.svg │ │ ├── 074_Pear Diamond.svg │ │ ├── 075_Maple Leaf.svg │ │ ├── 076_Eighteen Orbs and Crown in Chief.svg │ │ ├── 077_Croziers in Saltire and Star.svg │ │ ├── 077_Croziers in Saltire and Stars.svg │ │ ├── 078_Plough and Sun In Splendour.svg │ │ ├── 079_Telescope and Stars.svg │ │ ├── 080_Necklace.svg │ │ ├── 081_Pillar and Twin Quatrefoils.svg │ │ ├── 082_Horse-head Gables.svg │ │ ├── 083_Sextant.svg │ │ ├── 084_Lyre.svg │ │ ├── 085_Eye of Providence.svg │ │ ├── 086_Clockwork.svg │ │ ├── 087_Castle.svg │ │ ├── 088_Needle and Thread.svg │ │ ├── 089_Portcullis.svg │ │ ├── 090_Tree.svg │ │ ├── 091_Pugin Thistle.svg │ │ ├── 092_Gauntlet.svg │ │ ├── 093_Two Fleury Hinges Issuant from Dexter.svg │ │ ├── 094_Torch.svg │ │ ├── 095_Sun and Moon.svg │ │ ├── 096_Helm of the Esquire.svg │ │ ├── 097_Helm of the Knight.svg │ │ ├── 098_Helm of the Monarch.svg │ │ ├── 099_Vambraced Arm of the Warrior.svg │ │ ├── 100_Vambraced Arm of the Mage.svg │ │ ├── 101_Vambraced Arm of the Hunter.svg │ │ ├── 102_Palace Key.svg │ │ ├── 103_Vault Key.svg │ │ ├── 104_Dungeon Key.svg │ │ ├── 105_Chain Palewise.svg │ │ ├── 106_Cross Saltire and Orle of Chains.svg │ │ ├── 107_Chain Maille.svg │ │ ├── 108_Trypto Plate.svg │ │ ├── 109_Bordure Plate.svg │ │ ├── 110_Inverted Pall Plate.svg │ │ ├── 111_Escarbuncle.svg │ │ ├── 112_Tracery.svg │ │ ├── 113_Starfield.svg │ │ ├── 114_Wings.svg │ │ ├── 115_Skull.svg │ │ ├── 116_Rose.svg │ │ ├── 117_Shields Plate.svg │ │ ├── 118_Shields Bracket.svg │ │ ├── 119_The Book of Shields.svg │ │ └── 120_Three Shields.svg └── shared │ ├── buildShield.ts │ ├── colors.ts │ ├── deployFieldGenerator.ts │ ├── deployFrameGenerator.ts │ ├── deployHardwareGenerator.ts │ ├── deployTestFieldGenerator.ts │ ├── deployTestHardwareGenerator.ts │ ├── encodeColors.ts │ ├── expect.ts │ ├── extractJSONFromURI.ts │ ├── printSVGToSnapshots.ts │ └── snapshotGasCost.ts ├── tsconfig.json └── yarn.lock /.gitattributes: -------------------------------------------------------------------------------- 1 | *.sol linguist-language=Solidity -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | artifacts/ 2 | cache/ 3 | crytic-export/ 4 | node_modules/ 5 | typechain/ 6 | .env 7 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true, 4 | "printWidth": 120 5 | } 6 | -------------------------------------------------------------------------------- /.solhint.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["prettier"], 3 | "rules": { 4 | "prettier/prettier": "error" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /.yarnrc: -------------------------------------------------------------------------------- 1 | ignore-scripts true 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Shields 2 | 3 | Main repo for the Shields smart contracts. 4 | 5 | ## Deployment Addresses 6 | | Contract | Address | Source Code | 7 | | ---------------------------------- | -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | 8 | | Shields | `0x0747118C9F44C7a23365b2476dCD05E03114C747` | https://github.com/johncpalmer/ugp-crest-contracts/blob/aa7e312c20a8cb2526881a4436df4869fd0d87a7/contracts/Shields.sol | 9 | | EmblemWeaver | `0x3E2063199F7b98b8188B7649d95bd0C82f4B0001` | https://github.com/johncpalmer/ugp-crest-contracts/blob/aa7e312c20a8cb2526881a4436df4869fd0d87a7/contracts/EmblemWeaver.sol | 10 | | FieldGenerator | `0x0230eB753Df1A12063B357EB5e3A4F9Ce0780C1F` | https://github.com/johncpalmer/ugp-crest-contracts/blob/aa7e312c20a8cb2526881a4436df4869fd0d87a7/contracts/FieldGenerator.sol | 11 | | HardwareGenerator | `0x355944B17A0770190eCB375ec3E64b98Cb31a576` | https://github.com/johncpalmer/ugp-crest-contracts/blob/aa7e312c20a8cb2526881a4436df4869fd0d87a7/contracts/HardwareGenerator.sol | 12 | | FrameGenerator | `0x3b6cdEC2F91F4C7780C966B7Bfc6a8f55083863e` | https://github.com/johncpalmer/ugp-crest-contracts/blob/aa7e312c20a8cb2526881a4436df4869fd0d87a7/contracts/FrameGenerator.sol | 13 | | ShieldBadgeSVGs | `0xCCAc9aB49b53B7c228C47C55ac8B5704cFc57997` | https://github.com/johncpalmer/ugp-crest-contracts/blob/aa7e312c20a8cb2526881a4436df4869fd0d87a7/contracts/SVGs/ShieldBadgeSVGs.sol | 14 | 15 | All crest SVG addresses are listed in [deployedSVGs.json](https://github.com/johncpalmer/ugp-crest-contracts/blob/aa7e312c20a8cb2526881a4436df4869fd0d87a7/deploySVGs/deployedSVGs.json). 16 | 17 | ## Setup Instructions 18 | 19 | Must be running `node v14` or later. 20 | 21 | ### Testing 22 | 23 | First make sure you have run `yarn install` and `yarn run build`. 24 | 25 | ``` 26 | yarn run test 27 | ``` 28 | 29 | to update snapshots: 30 | ``` 31 | UPDATE_SNAPSHOT=1 yarn test 32 | ``` 33 | -------------------------------------------------------------------------------- /contracts/FrameGenerator.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: The Unlicense 2 | pragma solidity ^0.8.9; 3 | 4 | import './interfaces/IFrameGenerator.sol'; 5 | import './interfaces/IFrameSVGs.sol'; 6 | import '@openzeppelin/contracts/utils/Strings.sol'; 7 | 8 | /// @dev Generate Frame SVG and properties 9 | contract FrameGenerator is IFrameGenerator { 10 | using Strings for uint16; 11 | 12 | IFrameSVGs immutable frameSVGs1; 13 | IFrameSVGs immutable frameSVGs2; 14 | 15 | constructor(FrameSVGs memory svgs) { 16 | frameSVGs1 = svgs.frameSVGs1; 17 | frameSVGs2 = svgs.frameSVGs2; 18 | } 19 | 20 | function generateFrame(uint16 frame) external view override returns (IFrameSVGs.FrameData memory) { 21 | if (frame <= 3) { 22 | return callFrameSVGs(frameSVGs1, frame); 23 | } 24 | 25 | if (frame <= 5) { 26 | return callFrameSVGs(frameSVGs2, frame); 27 | } 28 | 29 | revert('invalid frame selection'); 30 | } 31 | 32 | function callFrameSVGs(IFrameSVGs target, uint16 frame) internal view returns (IFrameSVGs.FrameData memory) { 33 | bytes memory functionSelector = abi.encodePacked('frame_', uint16(frame).toString(), '()'); 34 | 35 | bool success; 36 | bytes memory result; 37 | (success, result) = address(target).staticcall(abi.encodeWithSelector(bytes4(keccak256(functionSelector)))); 38 | 39 | return abi.decode(result, (IFrameSVGs.FrameData)); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /contracts/interfaces/ICategories.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: The Unlicense 2 | pragma solidity ^0.8.9; 3 | 4 | interface ICategories { 5 | enum FieldCategories { 6 | MYTHIC, 7 | HERALDIC 8 | } 9 | 10 | enum HardwareCategories { 11 | STANDARD, 12 | SPECIAL 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /contracts/interfaces/IColors.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: The Unlicense 2 | pragma solidity ^0.8.9; 3 | 4 | interface IColors { 5 | event ColorAdded(uint24 color, string title); 6 | 7 | struct Color { 8 | string title; 9 | bool exists; 10 | } 11 | 12 | /// @notice Returns true if color exists in contract, else false. 13 | /// @param color 3-byte uint representing color 14 | /// @return true or false 15 | function colorExists(uint24 color) external view returns (bool); 16 | 17 | /// @notice Returns the title string corresponding to the 3-byte color 18 | /// @param color 3-byte uint representing color 19 | /// @return true or false 20 | function colorTitle(uint24 color) external view returns (string memory); 21 | } 22 | -------------------------------------------------------------------------------- /contracts/interfaces/IEmblemWeaver.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: The Unlicense 2 | pragma solidity ^0.8.9; 3 | 4 | import './IShields.sol'; 5 | import './IFrameGenerator.sol'; 6 | import './IFieldGenerator.sol'; 7 | import './IHardwareGenerator.sol'; 8 | 9 | /// @dev Generate Customizable Shields 10 | interface IEmblemWeaver { 11 | function fieldGenerator() external returns (IFieldGenerator); 12 | 13 | function hardwareGenerator() external returns (IHardwareGenerator); 14 | 15 | function frameGenerator() external returns (IFrameGenerator); 16 | 17 | function generateShieldURI(IShields.Shield memory shield) external view returns (string memory); 18 | 19 | function generateShieldBadgeURI(IShields.ShieldBadge shieldBadge) external view returns (string memory); 20 | } 21 | -------------------------------------------------------------------------------- /contracts/interfaces/IFieldGenerator.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: The Unlicense 2 | pragma solidity ^0.8.9; 3 | 4 | import './IFieldSVGs.sol'; 5 | import './IColors.sol'; 6 | 7 | /// @dev Generate Field SVG 8 | interface IFieldGenerator { 9 | /// @param field uint representing field selection 10 | /// @param colors to be rendered in the field svg 11 | /// @return FieldData containing svg snippet and field title 12 | function generateField(uint16 field, uint24[4] memory colors) external view returns (IFieldSVGs.FieldData memory); 13 | 14 | event ColorAdded(uint24 color, string title); 15 | 16 | struct Color { 17 | string title; 18 | bool exists; 19 | } 20 | 21 | /// @notice Returns true if color exists in contract, else false. 22 | /// @param color 3-byte uint representing color 23 | /// @return true or false 24 | function colorExists(uint24 color) external view returns (bool); 25 | 26 | /// @notice Returns the title string corresponding to the 3-byte color 27 | /// @param color 3-byte uint representing color 28 | /// @return true or false 29 | function colorTitle(uint24 color) external view returns (string memory); 30 | 31 | struct FieldSVGs { 32 | IFieldSVGs fieldSVGs1; 33 | IFieldSVGs fieldSVGs2; 34 | IFieldSVGs fieldSVGs3; 35 | IFieldSVGs fieldSVGs4; 36 | IFieldSVGs fieldSVGs5; 37 | IFieldSVGs fieldSVGs6; 38 | IFieldSVGs fieldSVGs7; 39 | IFieldSVGs fieldSVGs8; 40 | IFieldSVGs fieldSVGs9; 41 | IFieldSVGs fieldSVGs10; 42 | IFieldSVGs fieldSVGs11; 43 | IFieldSVGs fieldSVGs12; 44 | IFieldSVGs fieldSVGs13; 45 | IFieldSVGs fieldSVGs14; 46 | IFieldSVGs fieldSVGs15; 47 | IFieldSVGs fieldSVGs16; 48 | IFieldSVGs fieldSVGs17; 49 | IFieldSVGs fieldSVGs18; 50 | IFieldSVGs fieldSVGs19; 51 | IFieldSVGs fieldSVGs20; 52 | IFieldSVGs fieldSVGs21; 53 | IFieldSVGs fieldSVGs22; 54 | IFieldSVGs fieldSVGs23; 55 | IFieldSVGs fieldSVGs24; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /contracts/interfaces/IFieldSVGs.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: The Unlicense 2 | pragma solidity ^0.8.9; 3 | 4 | import './ICategories.sol'; 5 | 6 | interface IFieldSVGs { 7 | struct FieldData { 8 | string title; 9 | ICategories.FieldCategories fieldType; 10 | string svgString; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /contracts/interfaces/IFrameGenerator.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: The Unlicense 2 | pragma solidity ^0.8.9; 3 | 4 | import './IFrameSVGs.sol'; 5 | 6 | /// @dev Generate Frame SVG 7 | interface IFrameGenerator { 8 | struct FrameSVGs { 9 | IFrameSVGs frameSVGs1; 10 | IFrameSVGs frameSVGs2; 11 | } 12 | 13 | /// @param Frame uint representing Frame selection 14 | /// @return FrameData containing svg snippet and Frame title and Frame type 15 | function generateFrame(uint16 Frame) external view returns (IFrameSVGs.FrameData memory); 16 | } 17 | -------------------------------------------------------------------------------- /contracts/interfaces/IFrameSVGs.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: The Unlicense 2 | pragma solidity ^0.8.9; 3 | 4 | interface IFrameSVGs { 5 | struct FrameData { 6 | string title; 7 | uint256 fee; 8 | string svgString; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /contracts/interfaces/IHardwareGenerator.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: The Unlicense 2 | pragma solidity ^0.8.9; 3 | 4 | import './IHardwareSVGs.sol'; 5 | 6 | /// @dev Generate Hardware SVG 7 | interface IHardwareGenerator { 8 | 9 | /// @param hardware uint representing hardware selection 10 | /// @return HardwareData containing svg snippet and hardware title and hardware type 11 | function generateHardware(uint16 hardware) external view returns (IHardwareSVGs.HardwareData memory); 12 | 13 | struct HardwareSVGs { 14 | IHardwareSVGs hardwareSVGs1; 15 | IHardwareSVGs hardwareSVGs2; 16 | IHardwareSVGs hardwareSVGs3; 17 | IHardwareSVGs hardwareSVGs4; 18 | IHardwareSVGs hardwareSVGs5; 19 | IHardwareSVGs hardwareSVGs6; 20 | IHardwareSVGs hardwareSVGs7; 21 | IHardwareSVGs hardwareSVGs8; 22 | IHardwareSVGs hardwareSVGs9; 23 | IHardwareSVGs hardwareSVGs10; 24 | IHardwareSVGs hardwareSVGs11; 25 | IHardwareSVGs hardwareSVGs12; 26 | IHardwareSVGs hardwareSVGs13; 27 | IHardwareSVGs hardwareSVGs14; 28 | IHardwareSVGs hardwareSVGs15; 29 | IHardwareSVGs hardwareSVGs16; 30 | IHardwareSVGs hardwareSVGs17; 31 | IHardwareSVGs hardwareSVGs18; 32 | IHardwareSVGs hardwareSVGs19; 33 | IHardwareSVGs hardwareSVGs20; 34 | IHardwareSVGs hardwareSVGs21; 35 | IHardwareSVGs hardwareSVGs22; 36 | IHardwareSVGs hardwareSVGs23; 37 | IHardwareSVGs hardwareSVGs24; 38 | IHardwareSVGs hardwareSVGs25; 39 | IHardwareSVGs hardwareSVGs26; 40 | IHardwareSVGs hardwareSVGs27; 41 | IHardwareSVGs hardwareSVGs28; 42 | IHardwareSVGs hardwareSVGs29; 43 | IHardwareSVGs hardwareSVGs30; 44 | IHardwareSVGs hardwareSVGs31; 45 | IHardwareSVGs hardwareSVGs32; 46 | IHardwareSVGs hardwareSVGs33; 47 | IHardwareSVGs hardwareSVGs34; 48 | IHardwareSVGs hardwareSVGs35; 49 | IHardwareSVGs hardwareSVGs36; 50 | IHardwareSVGs hardwareSVGs37; 51 | IHardwareSVGs hardwareSVGs38; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /contracts/interfaces/IHardwareSVGs.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: The Unlicense 2 | pragma solidity ^0.8.9; 3 | 4 | import './ICategories.sol'; 5 | 6 | interface IHardwareSVGs { 7 | struct HardwareData { 8 | string title; 9 | ICategories.HardwareCategories hardwareType; 10 | string svgString; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /contracts/interfaces/IShieldBadgeSVGs.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: The Unlicense 2 | pragma solidity ^0.8.9; 3 | 4 | import './IShields.sol'; 5 | 6 | /// @dev Generate ShieldBadge SVG 7 | interface IShieldBadgeSVGs { 8 | function generateShieldBadgeSVG(IShields.ShieldBadge shieldBadge) external view returns (string memory); 9 | } 10 | -------------------------------------------------------------------------------- /contracts/interfaces/IShields.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: The Unlicense 2 | pragma solidity ^0.8.9; 3 | 4 | import '@openzeppelin/contracts/token/ERC721/IERC721.sol'; 5 | import '@openzeppelin/contracts/access/Ownable.sol'; 6 | import '@openzeppelin/contracts/utils/Strings.sol'; 7 | 8 | /// @dev Build Customizable Shields for an NFT 9 | interface IShields is IERC721 { 10 | enum ShieldBadge { 11 | MAKER, 12 | STANDARD 13 | } 14 | 15 | struct Shield { 16 | bool built; 17 | uint16 field; 18 | uint16 hardware; 19 | uint16 frame; 20 | ShieldBadge shieldBadge; 21 | uint24[4] colors; 22 | } 23 | 24 | function build( 25 | uint16 field, 26 | uint16 hardware, 27 | uint16 frame, 28 | uint24[4] memory colors, 29 | uint256 tokenId 30 | ) external payable; 31 | 32 | function shields(uint256 tokenId) 33 | external 34 | view 35 | returns ( 36 | uint16 field, 37 | uint16 hardware, 38 | uint16 frame, 39 | uint24 color1, 40 | uint24 color2, 41 | uint24 color3, 42 | uint24 color4, 43 | ShieldBadge shieldBadge 44 | ); 45 | } 46 | -------------------------------------------------------------------------------- /contracts/libraries/HexStrings.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.9; 3 | 4 | library HexStrings { 5 | bytes16 internal constant ALPHABET = '0123456789abcdef'; 6 | 7 | function toHexStringNoPrefix(uint256 value, uint256 length) internal pure returns (string memory) { 8 | bytes memory buffer = new bytes(2 * length); 9 | for (uint256 i = buffer.length; i > 0; i--) { 10 | buffer[i - 1] = ALPHABET[value & 0xf]; 11 | value >>= 4; 12 | } 13 | return string(buffer); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /contracts/test/EmblemWeaverTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: The Unlicense 2 | pragma solidity ^0.8.9; 3 | 4 | import '../interfaces/IShields.sol'; 5 | import '../interfaces/IFrameGenerator.sol'; 6 | import '../interfaces/IFieldGenerator.sol'; 7 | import '../interfaces/IHardwareGenerator.sol'; 8 | import '../EmblemWeaver.sol'; 9 | 10 | /// @dev Generate Shield Metadata 11 | contract EmblemWeaverTest is EmblemWeaver { 12 | constructor( 13 | IFieldGenerator _fieldGenerator, 14 | IHardwareGenerator _hardwareGenerator, 15 | IFrameGenerator _frameGenerator, 16 | IShieldBadgeSVGs _shieldBadgeSVGGenerator 17 | ) EmblemWeaver(_fieldGenerator, _hardwareGenerator, _frameGenerator, _shieldBadgeSVGGenerator) {} 18 | 19 | function generateSVGTest(IShields.Shield memory shield) 20 | external 21 | view 22 | returns ( 23 | string memory svg, 24 | string memory fieldTitle, 25 | string memory hardwareTitle, 26 | string memory frameTitle 27 | ) 28 | { 29 | IFieldSVGs.FieldData memory field = fieldGenerator.generateField(shield.field, shield.colors); 30 | IHardwareSVGs.HardwareData memory hardware = hardwareGenerator.generateHardware(shield.hardware); 31 | IFrameSVGs.FrameData memory frame = frameGenerator.generateFrame(shield.frame); 32 | 33 | svg = string(generateSVG(field.svgString, hardware.svgString, frame.svgString)); 34 | fieldTitle = field.title; 35 | hardwareTitle = hardware.title; 36 | frameTitle = frame.title; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /contracts/test/ShieldsGasTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: The Unlicense 2 | pragma solidity ^0.8.9; 3 | 4 | import '../Shields.sol'; 5 | 6 | /// @dev Generate Customizable Shields 7 | contract ShieldsGasTest { 8 | Shields public immutable shields; 9 | 10 | constructor(Shields _shields) { 11 | shields = _shields; 12 | } 13 | 14 | function gasSnapshotTokenURI(uint256 tokenId) public view returns (uint256) { 15 | uint256 gasBefore = gasleft(); 16 | shields.tokenURI(tokenId); 17 | return gasBefore - gasleft(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /contracts/test/ShieldsTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: The Unlicense 2 | pragma solidity ^0.8.9; 3 | 4 | import '../Shields.sol'; 5 | import '../interfaces/IFieldSVGs.sol'; 6 | import '../interfaces/IHardwareSVGs.sol'; 7 | import '../interfaces/IFrameSVGs.sol'; 8 | import '../interfaces/IShieldBadgeSVGs.sol'; 9 | 10 | /// @dev Generate Customizable Shields 11 | contract ShieldsTest is Shields { 12 | constructor( 13 | string memory name_, 14 | string memory symbol_, 15 | IEmblemWeaver _emblemWeaver, 16 | address _makerBadgeRecipient, 17 | address _granteeBadgeRecipient 18 | ) Shields(name_, symbol_, _emblemWeaver, _makerBadgeRecipient, _granteeBadgeRecipient) {} 19 | 20 | function getNextId() external view returns (uint256) { 21 | return _nextId; 22 | } 23 | 24 | function setNextId(uint256 nextId) external { 25 | _nextId = nextId; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /contracts/test/TestFieldGenerator.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: The Unlicense 2 | pragma solidity ^0.8.9; 3 | 4 | import '../interfaces/IFieldGenerator.sol'; 5 | import '../interfaces/IFieldSVGs.sol'; 6 | import '@openzeppelin/contracts/utils/Strings.sol'; 7 | 8 | /// @dev Test Field Generator with less SVGs / less deploy overhead 9 | contract TestFieldGenerator is IFieldGenerator { 10 | using Strings for uint16; 11 | 12 | mapping(uint24 => Color) public _colors; 13 | 14 | struct TestFieldSVGs { 15 | IFieldSVGs fieldSVGs1; 16 | IFieldSVGs fieldSVGs2; 17 | } 18 | 19 | IFieldSVGs immutable fieldSVGs1; 20 | IFieldSVGs immutable fieldSVGs2; 21 | 22 | constructor( 23 | uint24[] memory __colors, 24 | string[] memory titles, 25 | TestFieldSVGs memory svgs 26 | ) { 27 | require(__colors.length == titles.length, 'invalid array lengths'); 28 | for (uint256 i = 0; i < __colors.length; i++) { 29 | _colors[__colors[i]] = Color({title: titles[i], exists: true}); 30 | emit ColorAdded(__colors[i], titles[i]); 31 | } 32 | 33 | fieldSVGs1 = svgs.fieldSVGs1; 34 | fieldSVGs2 = svgs.fieldSVGs2; 35 | } 36 | 37 | function colorExists(uint24 color) public view override returns (bool) { 38 | return _colors[color].exists; 39 | } 40 | 41 | function colorTitle(uint24 color) public view override returns (string memory) { 42 | return _colors[color].title; 43 | } 44 | 45 | function callFieldSVGs( 46 | IFieldSVGs target, 47 | uint16 field, 48 | uint24[4] memory colors 49 | ) internal view returns (IFieldSVGs.FieldData memory) { 50 | bytes memory functionSelector = abi.encodePacked('field_', uint16(field).toString(), '(uint24[4])'); 51 | 52 | bool success; 53 | bytes memory result; 54 | (success, result) = address(target).staticcall( 55 | abi.encodeWithSelector(bytes4(keccak256(functionSelector)), colors) 56 | ); 57 | 58 | return abi.decode(result, (IFieldSVGs.FieldData)); 59 | } 60 | 61 | function generateField(uint16 field, uint24[4] memory colors) 62 | external 63 | view 64 | override 65 | returns (IFieldSVGs.FieldData memory) 66 | { 67 | if (field <= 28) { 68 | return callFieldSVGs(fieldSVGs1, field, colors); 69 | } 70 | 71 | if (field <= 50) { 72 | return callFieldSVGs(fieldSVGs2, field, colors); 73 | } 74 | revert('invalid field selection'); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /contracts/test/TestHardwareGenerator.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: The Unlicense 2 | pragma solidity ^0.8.9; 3 | 4 | import '../interfaces/IHardwareGenerator.sol'; 5 | import '../interfaces/IHardwareSVGs.sol'; 6 | import '@openzeppelin/contracts/utils/Strings.sol'; 7 | 8 | /// @dev Test Hardware Generator with less SVGs / less deploy overhead 9 | contract TestHardwareGenerator is IHardwareGenerator { 10 | using Strings for uint16; 11 | 12 | IHardwareSVGs immutable hardwareSVGs1; 13 | // needed to scrounge for a MYTHIC hardware 14 | IHardwareSVGs immutable hardwareSVGs29; 15 | 16 | struct TestHardwardSVGs { 17 | IHardwareSVGs hardwareSVGs1; 18 | IHardwareSVGs hardwareSVGs29; 19 | } 20 | 21 | constructor(TestHardwardSVGs memory svgs) { 22 | hardwareSVGs1 = svgs.hardwareSVGs1; 23 | hardwareSVGs29 = svgs.hardwareSVGs29; 24 | } 25 | 26 | function callHardwareSVGs(IHardwareSVGs target, uint16 hardware) 27 | internal 28 | view 29 | returns (IHardwareSVGs.HardwareData memory) 30 | { 31 | bytes memory functionSelector = abi.encodePacked('hardware_', uint16(hardware).toString(), '()'); 32 | 33 | bool success; 34 | bytes memory result; 35 | (success, result) = address(target).staticcall(abi.encodeWithSelector(bytes4(keccak256(functionSelector)))); 36 | 37 | return abi.decode(result, (IHardwareSVGs.HardwareData)); 38 | } 39 | 40 | function generateHardware(uint16 hardware) external view override returns (IHardwareSVGs.HardwareData memory) { 41 | if (hardware <= 5) { 42 | return callHardwareSVGs(hardwareSVGs1, hardware); 43 | } 44 | 45 | // needed to scrounge for a MYTHIC hardware 46 | if (hardware == 96 || hardware == 97) { 47 | return callHardwareSVGs(hardwareSVGs29, hardware); 48 | } 49 | 50 | revert('invalid hardware selection'); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /deploy/01_deploy_field_generator.ts: -------------------------------------------------------------------------------- 1 | import { HardhatRuntimeEnvironment } from 'hardhat/types' 2 | import { DeployFunction } from 'hardhat-deploy/types' 3 | import fs from 'fs' 4 | 5 | const JSON_PATH = 'deploySVGs/deployedSVGs.json' 6 | 7 | const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { 8 | const { deployer } = await hre.getNamedAccounts() 9 | const { deploy } = hre.deployments 10 | 11 | const deploymentArchive = JSON.parse(fs.readFileSync(JSON_PATH, { encoding: 'utf8' })) 12 | 13 | const colorHex = [ 14 | 0xff007a, 0x6c28a2, 0xfe7fff, 0xd3d3d3, 0x323232, 0x78503c, 0x007fff, 0xb5000a, 0xff6b00, 0xffb300, 0x006351, 15 | 0xceff00, 16 | ] 17 | 18 | const colorNames = [ 19 | 'Pink', 20 | 'Ultraviolet', 21 | 'Rose', 22 | 'Gray', 23 | 'Onyx', 24 | 'Brown', 25 | 'Sky', 26 | 'Crimson', 27 | 'Citrine', 28 | 'Gold', 29 | 'Evergreen', 30 | 'Hi-Vis', 31 | ] 32 | 33 | await deploy('FieldGenerator', { 34 | from: deployer, 35 | args: [colorHex, colorNames, deploymentArchive.fields], 36 | log: true, 37 | autoMine: true, // speed up deployment on local network (ganache, hardhat), no effect on live networks 38 | maxFeePerGas: hre.ethers.BigNumber.from('95000000000'), 39 | }) 40 | } 41 | export default func 42 | func.id = 'deploy_FieldGenerator' // id required to prevent reexecution 43 | func.tags = ['Shields'] 44 | -------------------------------------------------------------------------------- /deploy/02_deploy_hardware_generator.ts: -------------------------------------------------------------------------------- 1 | import { HardhatRuntimeEnvironment } from 'hardhat/types' 2 | import { DeployFunction } from 'hardhat-deploy/types' 3 | import fs from 'fs' 4 | 5 | const JSON_PATH = 'deploySVGs/deployedSVGs.json' 6 | 7 | const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { 8 | const { deployer } = await hre.getNamedAccounts() 9 | const { deploy } = hre.deployments 10 | 11 | const svgDeploymentArchive = JSON.parse(fs.readFileSync(JSON_PATH, { encoding: 'utf8' })) 12 | 13 | await deploy('HardwareGenerator', { 14 | from: deployer, 15 | args: [svgDeploymentArchive.hardwares], 16 | log: true, 17 | autoMine: true, // speed up deployment on local network (ganache, hardhat), no effect on live networks 18 | maxFeePerGas: hre.ethers.BigNumber.from('110000000000'), 19 | }) 20 | } 21 | export default func 22 | func.id = 'deploy_HardwareGenerator' // id required to prevent reexecution 23 | func.tags = ['Shields'] 24 | -------------------------------------------------------------------------------- /deploy/03_deploy_frame_generator.ts: -------------------------------------------------------------------------------- 1 | import { HardhatRuntimeEnvironment } from 'hardhat/types' 2 | import { DeployFunction } from 'hardhat-deploy/types' 3 | import fs from 'fs' 4 | 5 | const JSON_PATH = 'deploySVGs/deployedSVGs.json' 6 | 7 | const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { 8 | const { deployer } = await hre.getNamedAccounts() 9 | const { deploy } = hre.deployments 10 | 11 | const svgDeploymentArchive = JSON.parse(fs.readFileSync(JSON_PATH, { encoding: 'utf8' })) 12 | 13 | await deploy('FrameGenerator', { 14 | from: deployer, 15 | args: [svgDeploymentArchive.frames], 16 | log: true, 17 | autoMine: true, // speed up deployment on local network (ganache, hardhat), no effect on live networks 18 | maxFeePerGas: hre.ethers.BigNumber.from('95000000000'), 19 | }) 20 | } 21 | export default func 22 | func.id = 'deploy_FrameGenerator' // id required to prevent reexecution 23 | func.tags = ['Shields'] 24 | -------------------------------------------------------------------------------- /deploy/04_deploy_shieldbadgesvgs.ts: -------------------------------------------------------------------------------- 1 | import { HardhatRuntimeEnvironment } from 'hardhat/types' 2 | import { DeployFunction } from 'hardhat-deploy/types' 3 | 4 | const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { 5 | const { deployer } = await hre.getNamedAccounts() 6 | const { deploy } = hre.deployments 7 | 8 | await deploy('ShieldBadgeSVGs', { 9 | from: deployer, 10 | log: true, 11 | autoMine: true, // speed up deployment on local network (ganache, hardhat), no effect on live networks 12 | maxFeePerGas: hre.ethers.BigNumber.from('95000000000'), 13 | }) 14 | } 15 | export default func 16 | func.id = 'deploy_ShieldBadgeSVGs' // id required to prevent reexecution 17 | // Question: Should this tag be renamed to Shields? 18 | func.tags = ['Shields'] 19 | -------------------------------------------------------------------------------- /deploy/05_deploy_emblem_weaver.ts: -------------------------------------------------------------------------------- 1 | import { HardhatRuntimeEnvironment } from 'hardhat/types' 2 | import { DeployFunction } from 'hardhat-deploy/types' 3 | import fs from 'fs' 4 | 5 | const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { 6 | const { deployer } = await hre.getNamedAccounts() 7 | const { deploy } = hre.deployments 8 | const FieldGenerator = await hre.ethers.getContract('FieldGenerator') 9 | const HardwareGenerator = await hre.ethers.getContract('HardwareGenerator') 10 | const FrameGenerator = await hre.ethers.getContract('FrameGenerator') 11 | const ShieldBadgeSVGs = await hre.ethers.getContract('ShieldBadgeSVGs') 12 | 13 | await deploy('EmblemWeaver', { 14 | from: deployer, 15 | args: [FieldGenerator.address, HardwareGenerator.address, FrameGenerator.address, ShieldBadgeSVGs.address], 16 | log: true, 17 | autoMine: true, // speed up deployment on local network (ganache, hardhat), no effect on live networks 18 | maxFeePerGas: hre.ethers.BigNumber.from('95000000000'), 19 | }) 20 | } 21 | export default func 22 | func.id = 'deploy_EmblemWeaver' // id required to prevent reexecution 23 | // Question: Should this be renamed to Shields? 24 | func.tags = ['Shields'] 25 | -------------------------------------------------------------------------------- /deploy/06_deploy_shields.ts: -------------------------------------------------------------------------------- 1 | import { HardhatRuntimeEnvironment } from 'hardhat/types' 2 | import { DeployFunction } from 'hardhat-deploy/types' 3 | import fs from 'fs' 4 | 5 | const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { 6 | const { deployer } = await hre.getNamedAccounts() 7 | const { deploy } = hre.deployments 8 | const EmblemWeaver = await hre.ethers.getContract('EmblemWeaver') 9 | 10 | await deploy('Shields', { 11 | from: deployer, 12 | args: [ 13 | 'Shields', 14 | 'SHIELDS', 15 | EmblemWeaver.address, 16 | '0x42aaEEe1201EC5D1f3a3DCcc23AB8c01391d182d', 17 | '0x5e14ed9dCeE22ba758E8de482301028b261c4a14', 18 | ], 19 | log: true, 20 | autoMine: true, // speed up deployment on local network (ganache, hardhat), no effect on live networks 21 | maxFeePerGas: hre.ethers.BigNumber.from('95000000000'), 22 | }) 23 | } 24 | export default func 25 | func.id = 'deploy_Shields' // id required to prevent reexecution 26 | func.tags = ['Shields'] 27 | -------------------------------------------------------------------------------- /deploy/07_transfer_ownership.ts: -------------------------------------------------------------------------------- 1 | import { HardhatRuntimeEnvironment } from 'hardhat/types' 2 | import { DeployFunction } from 'hardhat-deploy/types' 3 | import fs from 'fs' 4 | import { Shields } from '../typechain' 5 | 6 | const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { 7 | const { deployer } = await hre.getNamedAccounts() 8 | const { deploy } = hre.deployments 9 | const shields = (await hre.ethers.getContract('Shields')) as Shields 10 | 11 | console.log( 12 | await shields.transferOwnership('0x42aaEEe1201EC5D1f3a3DCcc23AB8c01391d182d', { 13 | maxFeePerGas: hre.ethers.BigNumber.from('300000000000'), 14 | }) 15 | ) 16 | } 17 | export default func 18 | func.id = 'shields_premint' // id required to prevent reexecution 19 | func.tags = ['Shields'] 20 | -------------------------------------------------------------------------------- /deploySVGs/helpers.ts: -------------------------------------------------------------------------------- 1 | import web3Utils from 'web3-utils' 2 | import { ethers } from 'hardhat' 3 | import { ContractFactory } from 'ethers' 4 | 5 | export const SALT = '0x0000000000000000000000000000000000000000000000000000000000000000' 6 | export const SINGLETON_FACTORY_ADDRESS = '0xce0042B868300000d44A59004Da54A005ffdcf9f' 7 | export const SINGLETON_FACTORY_INTERFACE = new ethers.utils.Interface([ 8 | 'function deploy(bytes memory _initCode, bytes32 _salt)', 9 | ]) 10 | 11 | export type DeployedSVGs = { 12 | [contractName: string]: string 13 | } 14 | 15 | export type DeployedContracts = { 16 | [svgType: string]: DeployedSVGs 17 | } 18 | 19 | export type DeployedContractReceipt = { 20 | contractName: string 21 | address: string 22 | transactionHash?: string 23 | } 24 | 25 | export type DeployStatus = { 26 | deployed: boolean 27 | contractFactory: ContractFactory 28 | receipt: DeployedContractReceipt 29 | } 30 | 31 | export function constructDeploymentArchive( 32 | svgType: string, 33 | receipt: DeployedContractReceipt, 34 | deployedContracts: DeployedContracts 35 | ): DeployedContracts { 36 | svgType = `${svgType.toLowerCase()}s` 37 | deployedContracts[svgType][lowercaseFirst(receipt.contractName)] = receipt.address 38 | return deployedContracts 39 | } 40 | 41 | export function computeAddress(initcode: string): string { 42 | const codeHash = web3Utils.soliditySha3({ t: 'bytes', v: initcode }) 43 | if (!codeHash) { 44 | throw 'No codehash' 45 | } 46 | const addressAsBytes32 = web3Utils.soliditySha3( 47 | { t: 'uint8', v: 255 }, // 0xff 48 | { t: 'address', v: SINGLETON_FACTORY_ADDRESS }, 49 | { t: 'bytes32', v: SALT }, 50 | { t: 'bytes32', v: codeHash } 51 | ) 52 | return `0x${addressAsBytes32!.slice(26, 66)}` 53 | } 54 | 55 | function lowercaseFirst(str: string): string { 56 | return str[0].toLowerCase() + str.slice(1) 57 | } 58 | -------------------------------------------------------------------------------- /deployments/goerli/.chainId: -------------------------------------------------------------------------------- 1 | 5 -------------------------------------------------------------------------------- /deployments/mainnet/.chainId: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /deployments/rinkeby/.chainId: -------------------------------------------------------------------------------- 1 | 4 -------------------------------------------------------------------------------- /fields.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Area-Technology/shields-contracts/f0d9058bf82f394b84bdaa67f466766a7258637c/fields.txt -------------------------------------------------------------------------------- /hardhat.config.ts: -------------------------------------------------------------------------------- 1 | import 'hardhat-deploy' 2 | import 'hardhat-typechain' 3 | import '@nomiclabs/hardhat-ethers' 4 | import '@nomiclabs/hardhat-waffle' 5 | import '@nomiclabs/hardhat-etherscan' 6 | import dotenv from 'dotenv' 7 | dotenv.config() 8 | 9 | const DEFAULT_COMPILER_SETTINGS = { 10 | version: '0.8.9', 11 | settings: { 12 | optimizer: { 13 | enabled: false, 14 | }, 15 | metadata: { 16 | // do not include the metadata hash, since this is machine dependent 17 | // and we want all generated code to be deterministic 18 | // https://docs.soliditylang.org/en/v0.7.6/metadata.html 19 | bytecodeHash: 'none', 20 | }, 21 | }, 22 | } 23 | 24 | const OPTIMIZED_COMPILER_SETTINGS = { 25 | version: '0.8.9', 26 | settings: { 27 | optimizer: { 28 | enabled: true, 29 | runs: 1_000_000, 30 | }, 31 | metadata: { 32 | // do not include the metadata hash, since this is machine dependent 33 | // and we want all generated code to be deterministic 34 | // https://docs.soliditylang.org/en/v0.7.6/metadata.html 35 | bytecodeHash: 'none', 36 | }, 37 | }, 38 | } 39 | 40 | export default { 41 | networks: { 42 | hardhat: { 43 | allowUnlimitedContractSize: false, 44 | }, 45 | mainnet: { 46 | url: `https://mainnet.infura.io/v3/${process.env.INFURA_API_KEY}`, 47 | accounts: [process.env.MAINNET_DEPLOYER], 48 | }, 49 | ropsten: { 50 | url: `https://ropsten.infura.io/v3/${process.env.INFURA_API_KEY}`, 51 | }, 52 | rinkeby: { 53 | url: `https://rinkeby.infura.io/v3/${process.env.INFURA_API_KEY}`, 54 | accounts: [process.env.DEPLOYER], 55 | }, 56 | goerli: { 57 | url: `https://goerli.infura.io/v3/${process.env.INFURA_API_KEY}`, 58 | accounts: [process.env.DEPLOYER], 59 | }, 60 | kovan: { 61 | url: `https://kovan.infura.io/v3/${process.env.INFURA_API_KEY}`, 62 | }, 63 | }, 64 | namedAccounts: { 65 | deployer: 0, 66 | }, 67 | etherscan: { 68 | // Your API key for Etherscan 69 | // Obtain one at https://etherscan.io/ 70 | apiKey: process.env.ETHERSCAN_API_KEY, 71 | }, 72 | solidity: { 73 | compilers: [DEFAULT_COMPILER_SETTINGS], 74 | overrides: { 75 | 'contracts/Shields.sol': OPTIMIZED_COMPILER_SETTINGS, 76 | 'contracts/ShieldDescriptor.sol': OPTIMIZED_COMPILER_SETTINGS, 77 | 'contracts/FieldGenerator.sol': OPTIMIZED_COMPILER_SETTINGS, 78 | 'contracts/FrameGenerator.sol': OPTIMIZED_COMPILER_SETTINGS, 79 | 'contracts/HardwareGenerator.sol': OPTIMIZED_COMPILER_SETTINGS, 80 | }, 81 | }, 82 | mocha: { 83 | timeout: 60000, 84 | }, 85 | } 86 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "shields", 3 | "description": "Customizable Shield NFTs", 4 | "license": "GPL-3.0-or-later", 5 | "publishConfig": { 6 | "access": "restricted" 7 | }, 8 | "version": "1.0.0-alpha.0", 9 | "homepage": "", 10 | "keywords": [ 11 | "uniswap", 12 | "nft", 13 | "swap" 14 | ], 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/johncpalmer/ugp-crest-contracts" 18 | }, 19 | "files": [ 20 | "contracts/interfaces", 21 | "contracts/libraries", 22 | "artifacts/contracts/**/*.json", 23 | "!artifacts/contracts/**/*.dbg.json" 24 | ], 25 | "engines": { 26 | "node": ">=14" 27 | }, 28 | "dependencies": { 29 | "@openzeppelin/contracts": "v4.4.2", 30 | "base64-sol": "1.0.1" 31 | }, 32 | "devDependencies": { 33 | "@nomiclabs/hardhat-ethers": "npm:hardhat-deploy-ethers", 34 | "@nomiclabs/hardhat-etherscan": "^2.1.1", 35 | "@nomiclabs/hardhat-waffle": "^2.0.1", 36 | "@typechain/ethers-v5": "^4.0.0", 37 | "@types/chai": "^4.2.6", 38 | "@types/mocha": "^5.2.7", 39 | "chai": "^4.2.0", 40 | "dotenv": "^10.0.0", 41 | "ethereum-waffle": "^3.0.2", 42 | "ethers": "^5.0.8", 43 | "hardhat": "^2.2.0", 44 | "hardhat-deploy": "^0.9.6", 45 | "hardhat-typechain": "^0.3.5", 46 | "mocha": "^6.2.2", 47 | "mocha-chai-jest-snapshot": "^1.1.0", 48 | "prettier": "^2.0.5", 49 | "prettier-plugin-solidity": "^1.0.0-alpha.59", 50 | "solhint": "^3.2.1", 51 | "solhint-plugin-prettier": "^0.0.5", 52 | "ts-generator": "^0.1.1", 53 | "ts-node": "^8.5.4", 54 | "typechain": "^4.0.0", 55 | "typescript": "^3.7.3", 56 | "web3-utils": "^1.3.6" 57 | }, 58 | "scripts": { 59 | "compile": "hardhat compile", 60 | "test": "hardhat test", 61 | "deploy": "hardhat deploy --network", 62 | "deploySVGs": "hardhat run deploySVGs/deployFieldSVGs.ts --network" 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /test/FieldSVGs.spec.ts: -------------------------------------------------------------------------------- 1 | import { FieldGenerator, FieldSVGs1 } from '../typechain' 2 | import { ethers, waffle } from 'hardhat' 3 | import { expect } from './shared/expect' 4 | import snapshotGasCost from './shared/snapshotGasCost' 5 | import fs from 'fs' 6 | import encodeColors from './shared/encodeColors' 7 | import { fieldColors, titles } from './shared/colors' 8 | import { BigNumber, BigNumberish } from 'ethers' 9 | import deployFieldGenerator from './shared/deployFieldGenerator' 10 | 11 | describe('FieldSVGs', async () => { 12 | let fields: FieldGenerator 13 | let fieldSVGs1: FieldSVGs1 14 | 15 | describe('constructor', () => { 16 | it('deployment gas', async () => { 17 | const asGasSnapshot = true 18 | await deployFieldGenerator(asGasSnapshot) 19 | }) 20 | 21 | it('bytecode size', async () => { 22 | const contract = await deployFieldGenerator() 23 | expect(((await contract.provider.getCode(contract.address)).length - 2) / 2).to.matchSnapshot() 24 | }) 25 | }) 26 | 27 | describe('IFieldSVGs deployment', () => { 28 | for (let i = 1; i <= 24; i++) { 29 | it(`FieldSVGs${i} has gas`, async () => { 30 | await snapshotGasCost((await ethers.getContractFactory(`FieldSVGs${i}`)).deploy()) 31 | }) 32 | 33 | it(`FieldSVGs${i} has bytecode`, async () => { 34 | const contract = await (await ethers.getContractFactory(`FieldSVGs${i}`)).deploy() 35 | expect(((await contract.provider.getCode(contract.address)).length - 2) / 2).to.matchSnapshot() 36 | }) 37 | } 38 | }) 39 | 40 | describe.skip('SVG Generation', () => { 41 | beforeEach(async () => { 42 | const fieldSVGs1 = (await (await ethers.getContractFactory('FieldSVGs1')).deploy()) as FieldSVGs1 43 | const fieldSVGs2 = (await (await ethers.getContractFactory('FieldSVGs2')).deploy()) as FieldSVGs1 44 | const contract = await ( 45 | await ethers.getContractFactory('FieldGenerator') 46 | ).deploy(fieldColors, titles, fieldSVGs1.address, fieldSVGs2.address) 47 | }) 48 | 49 | it('returns the correct field_one_color svg string', async () => { 50 | const color: [BigNumberish, BigNumberish, BigNumberish, BigNumberish] = [ 51 | BigNumber.from(0xdeadbe), 52 | BigNumber.from(0xdeadbe), 53 | BigNumber.from(0xdeadde), 54 | BigNumber.from(0xddadbe), 55 | ] 56 | 57 | const svg = await fields.generateField(0, color) 58 | expect(svg).toMatchSnapshot() 59 | }) 60 | 61 | it('returns the correct field_two_colors svg string', async () => { 62 | const color = encodeColors([0xdeadbe, 0xc1c1c1]) 63 | 64 | const svg = await fields.generateField(2, color) 65 | expect(svg).toMatchSnapshot() 66 | }) 67 | 68 | it('returns the correct field_three_colors svg string', async () => { 69 | const color = encodeColors([0xdeadbe, 0xc1c1c1, 0xf234ab]) 70 | 71 | const svg = await fields.generateField(293, color) 72 | expect(svg).toMatchSnapshot() 73 | }) 74 | 75 | it('returns the correct field_four_colors svg string', async () => { 76 | const color = encodeColors([0xdeadbe, 0xc1c1c1, 0xf234ab, 0x889933]) 77 | 78 | const svg = await fields.generateField(299, color) 79 | expect(svg).toMatchSnapshot() 80 | }) 81 | }) 82 | }) 83 | -------------------------------------------------------------------------------- /test/FrameSVGs.spec.ts: -------------------------------------------------------------------------------- 1 | import { FrameGenerator, FrameSVGs1 } from '../typechain' 2 | import { ethers, waffle } from 'hardhat' 3 | import { expect } from './shared/expect' 4 | import snapshotGasCost from './shared/snapshotGasCost' 5 | import deployFrameGenerator from './shared/deployFrameGenerator' 6 | import fs from 'fs' 7 | 8 | describe('FrameGenerator', async () => { 9 | let frames: FrameGenerator 10 | 11 | describe('constructor', () => { 12 | it('deployment gas', async () => { 13 | const asGasSnapshot = true 14 | await deployFrameGenerator(asGasSnapshot) 15 | }) 16 | 17 | it('bytecode size', async () => { 18 | const contract = (await deployFrameGenerator()) as FrameGenerator 19 | expect(((await contract.provider.getCode(contract.address)).length - 2) / 2).to.matchSnapshot() 20 | }) 21 | }) 22 | 23 | describe('IFrameSVGs deployment', () => { 24 | for (let i = 1; i <= 2; i++) { 25 | it(`FrameSVGs${i} has gas`, async () => { 26 | await snapshotGasCost((await ethers.getContractFactory(`FrameSVGs${i}`)).deploy()) 27 | }) 28 | 29 | it(`FrameSVGs${i} has bytecode`, async () => { 30 | const contract = await (await ethers.getContractFactory(`FrameSVGs${i}`)).deploy() 31 | expect(((await contract.provider.getCode(contract.address)).length - 2) / 2).to.matchSnapshot() 32 | }) 33 | } 34 | }) 35 | 36 | describe('SVG Generation', () => { 37 | it('returns the correct frame svg string', async () => { 38 | frames = (await deployFrameGenerator()) as FrameGenerator 39 | const frame = await frames.generateFrame(3) 40 | expect(frame).toMatchSnapshot() 41 | const svg = `${frame.svgString}` 42 | fs.writeFileSync('./test/__snapshots__/svgs/frame.svg', svg) 43 | }) 44 | }) 45 | }) 46 | -------------------------------------------------------------------------------- /test/HardwareSVGs.spec.ts: -------------------------------------------------------------------------------- 1 | import { HardwareGenerator, HardwareSVGs1 } from '../typechain' 2 | import { ethers, waffle } from 'hardhat' 3 | import { expect } from './shared/expect' 4 | import snapshotGasCost from './shared/snapshotGasCost' 5 | import deployHardwareGenerator from './shared/deployHardwareGenerator' 6 | import fs from 'fs' 7 | 8 | describe('HardwareGenerator', async () => { 9 | let hardwares: HardwareGenerator 10 | 11 | describe('constructor', () => { 12 | it('deployment gas', async () => { 13 | const asGasSnapshot = true 14 | await deployHardwareGenerator(asGasSnapshot) 15 | }) 16 | 17 | it('bytecode size', async () => { 18 | const contract = (await deployHardwareGenerator()) as HardwareGenerator 19 | expect(((await contract.provider.getCode(contract.address)).length - 2) / 2).to.matchSnapshot() 20 | }) 21 | }) 22 | 23 | describe('IHardwareSVGs deployment', () => { 24 | for (let i = 1; i <= 38; i++) { 25 | it(`HardwareSVGs${i} has gas`, async () => { 26 | await snapshotGasCost((await ethers.getContractFactory(`HardwareSVGs${i}`)).deploy()) 27 | }) 28 | 29 | it(`HardwareSVGs${i} has bytecode`, async () => { 30 | const contract = await (await ethers.getContractFactory(`HardwareSVGs${i}`)).deploy() 31 | expect(((await contract.provider.getCode(contract.address)).length - 2) / 2).to.matchSnapshot() 32 | }) 33 | } 34 | }) 35 | 36 | describe('SVG Generation', () => { 37 | it('returns the correct hardware svg string', async () => { 38 | hardwares = (await deployHardwareGenerator()) as HardwareGenerator 39 | const hardware = await hardwares.generateHardware(0) 40 | expect(hardware).toMatchSnapshot() 41 | const svg = `${hardware.svgString}` 42 | fs.writeFileSync('./test/__snapshots__/svgs/hardware.svg', svg) 43 | }) 44 | }) 45 | }) 46 | -------------------------------------------------------------------------------- /test/__snapshots__/EmblemWeaver.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`EmblemWeaver constructor deployment gas 1`] = `2622206`; 4 | 5 | exports[`EmblemWeaver constructor has bytecode size 1`] = `12692`; 6 | -------------------------------------------------------------------------------- /test/__snapshots__/ShieldDescriptor.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`EmblemWeaver constructor deployment gas 1`] = `2028334`; 4 | 5 | exports[`EmblemWeaver constructor has bytecode size 1`] = `12692`; 6 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Area-Technology/shields-contracts/f0d9058bf82f394b84bdaa67f466766a7258637c/test/__snapshots__/svgs/.DS_Store -------------------------------------------------------------------------------- /test/__snapshots__/svgs/fields/000_Perfect.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/fields/001_Per Pale.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/fields/068_Canton.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/fields/069_Canton Sinister.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/fields/070_Chief.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/fields/077_Chief Triangular.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/fields/111_Pile.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/fields/117_Gyron.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/fields/162_Billet.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/frames/000_.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/000_Bushing Hammer.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/001_Shovel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/002_Screw.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/003_Flathead Screwdriver.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/004_Pen Nib.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/005_Scissors.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/008_Tongs.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/009_Compass and Triangle.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/010_Magnifying Glass.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/011_Shears.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/014_Tuning Fork.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/015_Mallet with Chisels in Saltire.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/016_Hammer and Compass.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/018_Book.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/019_Calipers.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/020_Three Nails.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/021_Awl.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/022_French Key Wrench.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/024_Anvil.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/027_Jewelers Loupe.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/029_Cauldron.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/031_Lug Wrench and Four Lug Nuts.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/033_Rudder.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/034_Gavel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/037_Triskele Tracery.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/037_Triskele.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/039_Keyhole.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/040_Pitcher.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/054_Stack.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/055_Orb.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/056_Command in Canton.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/057_Three Chalices.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/058_Three Brushes.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/059_Three Writing Pens.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/060_Lead Holder and Twin Blades.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/065_Three Bells in Chief.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/066_Three Suns in Chief.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/068_Two Suns.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/069_Four Suns.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/070_Two Books.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/082_Horse-head Gables.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/105_Chain Palewise.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/109_Bordure Plate.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/110_Inverted Pall Plate.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/__snapshots__/svgs/hardware/120_Three Shields.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/shared/buildShield.ts: -------------------------------------------------------------------------------- 1 | import { Shields } from '../../typechain' 2 | import { BigNumber, BigNumberish, ContractTransaction } from 'ethers' 3 | import { ethers } from 'hardhat' 4 | 5 | type ShieldBuilt = { 6 | tx: ContractTransaction 7 | tokenId: string 8 | } 9 | 10 | export async function buildShield( 11 | shields: Shields, 12 | params: { 13 | field: number 14 | hardware: number 15 | frame: number 16 | colors: [BigNumberish, BigNumberish, BigNumberish, BigNumberish] 17 | fee: BigNumber 18 | to: string 19 | } 20 | ): Promise { 21 | const mintTx = await ( 22 | await shields.mint(params.to, 1, { value: BigNumber.from(ethers.utils.parseEther('0.15')) }) 23 | ).wait() 24 | const tokenId = mintTx.events![0].args!.tokenId 25 | const tx = await shields.build(params.field, params.hardware, params.frame, params.colors, tokenId, { 26 | value: params.fee, 27 | }) 28 | return { tx, tokenId } 29 | } 30 | -------------------------------------------------------------------------------- /test/shared/colors.ts: -------------------------------------------------------------------------------- 1 | const colorMap = new Map([ 2 | [0xfc03a5, 'radical red'], 3 | [0x5632a8, 'perfect pink'], 4 | [0x112233, 'bloo'], 5 | [0xaabbff, 'gothic green'], 6 | ]) 7 | const fieldColors = Array.from(colorMap.keys()) 8 | const titles = Array.from(colorMap.values()) 9 | 10 | export { colorMap, fieldColors, titles } 11 | -------------------------------------------------------------------------------- /test/shared/deployFrameGenerator.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from 'hardhat' 2 | import { FrameGenerator, FrameSVGs1 } from '../../typechain' 3 | import snapshotGasCost from './snapshotGasCost' 4 | 5 | export default async function deployFrameGenerator(asGasSnapshot?: boolean) { 6 | const frameSVGs1 = (await (await ethers.getContractFactory('FrameSVGs1')).deploy()) as FrameSVGs1 7 | const frameSVGs2 = (await (await ethers.getContractFactory('FrameSVGs2')).deploy()) as FrameSVGs1 8 | 9 | if (!!asGasSnapshot) { 10 | await snapshotGasCost( 11 | ( 12 | await ethers.getContractFactory('FrameGenerator') 13 | ).deploy({ frameSVGs1: frameSVGs1.address, frameSVGs2: frameSVGs2.address }) 14 | ) 15 | } 16 | 17 | const contract = (await ( 18 | await ethers.getContractFactory('FrameGenerator') 19 | ).deploy({ frameSVGs1: frameSVGs1.address, frameSVGs2: frameSVGs2.address })) as FrameGenerator 20 | return contract 21 | } 22 | -------------------------------------------------------------------------------- /test/shared/deployTestFieldGenerator.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from 'hardhat' 2 | import { FieldGenerator, FieldSVGs1 } from '../../typechain' 3 | import { fieldColors, titles } from './colors' 4 | import snapshotGasCost from './snapshotGasCost' 5 | 6 | export default async function deployTestFieldGenerator(asGasSnapshot?: boolean) { 7 | const fieldSVGs1 = (await (await ethers.getContractFactory('FieldSVGs1')).deploy()) as FieldSVGs1 8 | const fieldSVGs2 = (await (await ethers.getContractFactory('FieldSVGs2')).deploy()) as FieldSVGs1 9 | 10 | const svgs = { 11 | fieldSVGs1: fieldSVGs1.address, 12 | fieldSVGs2: fieldSVGs2.address, 13 | } 14 | 15 | if (!!asGasSnapshot) { 16 | await snapshotGasCost((await ethers.getContractFactory('TestFieldGenerator')).deploy(fieldColors, titles, svgs)) 17 | } 18 | 19 | const contract = (await ( 20 | await ethers.getContractFactory('TestFieldGenerator') 21 | ).deploy(fieldColors, titles, svgs)) as FieldGenerator 22 | return contract 23 | } 24 | -------------------------------------------------------------------------------- /test/shared/deployTestHardwareGenerator.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from 'hardhat' 2 | import { HardwareGenerator, HardwareSVGs1 } from '../../typechain' 3 | import snapshotGasCost from './snapshotGasCost' 4 | 5 | export default async function deployTestHardwareGenerator(asGasSnapshot?: boolean) { 6 | const hardwareSVGs1 = (await (await ethers.getContractFactory('HardwareSVGs1')).deploy()) as HardwareSVGs1 7 | const hardwareSVGs29 = (await (await ethers.getContractFactory('HardwareSVGs29')).deploy()) as HardwareSVGs1 8 | 9 | const svgs = { 10 | hardwareSVGs1: hardwareSVGs1.address, 11 | hardwareSVGs29: hardwareSVGs29.address, 12 | } 13 | 14 | if (!!asGasSnapshot) { 15 | await snapshotGasCost((await ethers.getContractFactory('TestHardwareGenerator')).deploy(svgs)) 16 | } 17 | 18 | const contract = (await (await ethers.getContractFactory('TestHardwareGenerator')).deploy(svgs)) as HardwareGenerator 19 | return contract 20 | } 21 | -------------------------------------------------------------------------------- /test/shared/encodeColors.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from 'hardhat' 2 | import { BigNumberish } from 'ethers' 3 | 4 | export default function encodeColors( 5 | colors: number[] | BigNumberish[] 6 | ): [BigNumberish, BigNumberish, BigNumberish, BigNumberish] { 7 | let colorArray: [BigNumberish, BigNumberish, BigNumberish, BigNumberish] = [0, 0, 0, 0] 8 | 9 | colors.forEach((color, index) => { 10 | colorArray[index] = color 11 | }) 12 | 13 | return colorArray 14 | } 15 | -------------------------------------------------------------------------------- /test/shared/expect.ts: -------------------------------------------------------------------------------- 1 | import { expect, use } from 'chai' 2 | import { solidity } from 'ethereum-waffle' 3 | import { jestSnapshotPlugin } from 'mocha-chai-jest-snapshot' 4 | 5 | use(solidity) 6 | use(jestSnapshotPlugin()) 7 | 8 | export { expect } 9 | -------------------------------------------------------------------------------- /test/shared/extractJSONFromURI.ts: -------------------------------------------------------------------------------- 1 | type attribute = { 2 | trait_type: string 3 | value: string 4 | } 5 | 6 | export function extractJSONFromURI(uri: string): { 7 | name: string 8 | description: string 9 | image: string 10 | attributes: Array 11 | } { 12 | const encodedJSON = uri.substr('data:application/json;base64,'.length) 13 | const decodedJSON = Buffer.from(encodedJSON, 'base64').toString('utf8') 14 | return JSON.parse(decodedJSON) 15 | } 16 | -------------------------------------------------------------------------------- /test/shared/printSVGToSnapshots.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs' 2 | 3 | export function printSVGToSnapshots(type: string, title: string, svgString: string) { 4 | fs.writeFileSync(`./test/__snapshots__/svgs/${type}/${title}.svg`, svgString) 5 | } 6 | -------------------------------------------------------------------------------- /test/shared/snapshotGasCost.ts: -------------------------------------------------------------------------------- 1 | import { TransactionReceipt, TransactionResponse } from '@ethersproject/abstract-provider' 2 | import { expect } from './expect' 3 | import { Contract, BigNumber, ContractTransaction } from 'ethers' 4 | 5 | export default async function snapshotGasCost( 6 | x: 7 | | TransactionResponse 8 | | Promise 9 | | ContractTransaction 10 | | Promise 11 | | TransactionReceipt 12 | | Promise 13 | | BigNumber 14 | | Contract 15 | | Promise 16 | ): Promise { 17 | const resolved = await x 18 | if ('deployTransaction' in resolved) { 19 | const receipt = await resolved.deployTransaction.wait() 20 | expect(receipt.gasUsed.toNumber()).toMatchSnapshot() 21 | } else if ('wait' in resolved) { 22 | const waited = await resolved.wait() 23 | expect(waited.gasUsed.toNumber()).toMatchSnapshot() 24 | } else if (BigNumber.isBigNumber(resolved)) { 25 | expect(resolved.toNumber()).toMatchSnapshot() 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2018", 4 | "module": "commonjs", 5 | "strict": true, 6 | "esModuleInterop": true, 7 | "outDir": "dist", 8 | "typeRoots": ["./typechain", "./node_modules/@types"], 9 | "types": ["@nomiclabs/hardhat-ethers", "@nomiclabs/hardhat-waffle"] 10 | }, 11 | "include": ["./test"], 12 | "files": ["./hardhat.config.ts"] 13 | } 14 | --------------------------------------------------------------------------------